Compare commits

...

599 Commits

Author SHA1 Message Date
katelyn martin e8cc4ec47b
nit(app): remove frivolous code (#4094)
this commit removes a piece of code that has been commented out.

it additionally removes a variable binding that is not needed. `dst` is
not moved, so we do not need to bind the address of the destination
service to a variable, nor do we need to clone it.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-08-20 11:31:09 -04:00
dependabot[bot] b951a6c374
build(deps): bump tempfile from 3.20.0 to 3.21.0 (#4093)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.20.0 to 3.21.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/commits)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-version: 3.21.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-20 10:13:45 -04:00
dependabot[bot] 7f6ac15f13
build(deps): bump cfg-if from 1.0.1 to 1.0.3 (#4092)
Bumps [cfg-if](https://github.com/rust-lang/cfg-if) from 1.0.1 to 1.0.3.
- [Release notes](https://github.com/rust-lang/cfg-if/releases)
- [Changelog](https://github.com/rust-lang/cfg-if/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cfg-if/compare/v1.0.1...v1.0.3)

---
updated-dependencies:
- dependency-name: cfg-if
  dependency-version: 1.0.3
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-20 10:13:04 -04:00
dependabot[bot] 75e9caaeae
build(deps): bump thiserror from 2.0.15 to 2.0.16 (#4091)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.15 to 2.0.16.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.15...2.0.16)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-version: 2.0.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-20 10:12:43 -04:00
dependabot[bot] 02bbb3d617
build(deps): bump prettyplease from 0.2.36 to 0.2.37 (#4090)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.36 to 0.2.37.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.36...0.2.37)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-version: 0.2.37
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 15:40:53 -04:00
dependabot[bot] 103c69ca75
build(deps): bump serde_json from 1.0.142 to 1.0.143 (#4088)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.142 to 1.0.143.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.142...v1.0.143)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-version: 1.0.143
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 15:40:39 -04:00
dependabot[bot] 4663cc4eb6
build(deps): bump tinyvec from 1.9.0 to 1.10.0 (#4087)
Bumps [tinyvec](https://github.com/Lokathor/tinyvec) from 1.9.0 to 1.10.0.
- [Changelog](https://github.com/Lokathor/tinyvec/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Lokathor/tinyvec/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: tinyvec
  dependency-version: 1.10.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 15:40:31 -04:00
dependabot[bot] 03374b9543
build(deps): bump hyper from 1.6.0 to 1.7.0 (#4089)
Bumps [hyper](https://github.com/hyperium/hyper) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/hyperium/hyper/releases)
- [Changelog](https://github.com/hyperium/hyper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: hyper
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 15:40:03 -04:00
Scott Fleener 4c9ae74450 chore(metrics): Use `linkerd-rustls` for crypto provider metrics
Now that the `rustls` initialization/configuration has been decoupled from `linkerd-meshtls`, we can get the provider directly from there. This handles the uninitialized case better, which should be less of a problem now that we always directly initialize the provider in main.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-19 14:06:32 -04:00
katelyn martin 94572d174d
refactor(http/classify): remove unused classification middleware (#4085)
`NewBroadcastClassification<C, X, N>` is not used.

`BroadcastClassification<C, S>` is only used by the `gate` submodule in
this crate.

this commit removes `NewBroadcastClassification`, since it is unused.
this commit demotes `channel` to an internal submodule, since it has no
external users.

the reëxport of `BroadcastClassification` is unused, though it is left
intact because it _is_ exposed by `NewClassifyGateSet`'s implementation
of `NewService<T>`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-08-19 09:33:29 -04:00
katelyn martin 897c7e85bc
refactor(app/core): remove unused `gate` reëxport (#4084)
`linkerd_app_core::classify` reëxports symbols from
`linkerd_proxy_http::classify::gate`.

nothing makes use of this, and these symbols are already reëxported from
`linkerd_proxy_http::classify`. existing callsites in the outbound proxy
import this middleware directly, or though the reëxport in
`linkerd_proxy_http`.

this commit removes this `pub use` directive, since it does nothing.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-08-18 20:58:18 +00:00
Scott Fleener 036ca75c00
chore(tls): Install default rustls provider in main (#4083)
* chore(tls): Move rustls into dedicated crate

Signed-off-by: Scott Fleener <scott@buoyant.io>

* chore(tls): Remove extraneous provider installs from tests

Signed-off-by: Scott Fleener <scott@buoyant.io>

* chore(tls): Install default rustls provider in main

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-18 19:55:09 +00:00
Scott Fleener 98e731d841
chore(tls): Move `rustls` configuration into dedicated crate (#4082)
* chore(tls): Move rustls into dedicated crate

Signed-off-by: Scott Fleener <scott@buoyant.io>

* chore(tls): Remove extraneous provider installs from tests

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-18 12:48:28 -07:00
Scott Fleener d5b12ea5e2 chore(tls): Hoist rustls directly into linkerd-meshtls
Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-18 15:37:05 -04:00
Scott Fleener a64170bd61
chore(tls): Refactor `rustls` shims out of `linkerd-meshtls` (#4080)
* chore(tls): Refactor shims out of meshtls

Meshtls previously assumed that mutliple TLS implementations could be used. Now that we've consolidated on rustls as the TLS implementation, we can remove these shims.

Signed-off-by: Scott Fleener <scott@buoyant.io>

* chore(tls): Refactor mode out of meshtls

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-18 12:27:09 -07:00
katelyn martin 973dfa6f4d
refactor(app/inbound): remove unused `proxy_metrics()` method (#4079)
this commit removes `linkerd_app_inbound::Inbound::proxy_metrics()`.

this accessor is not used anywhere.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-08-18 14:36:31 -04:00
Scott Fleener 17bff6144a
feat(tls): Explicitly include post-quantum key exchange algorithms (#4070)
* feat(tls): Explicitly include post-quantum key exchange algorithms

This explicitly sets the key exchange algorithms the proxy uses. It adds `X25519MLKEM768` as the most preferred algorithm in non-FIPS mode, and `SECP256R1MLKEM768` in FIPS mode.

Note that `X25519MLKEM768` is still probably appropriate for FIPS environments according to [NIST's special publication 800-56Cr2](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf) as it performs a FIPS-approved key-establishment first (`MLKEM768`), but we should evaluate this position more before committing to it.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-18 14:09:34 -04:00
katelyn martin d385094caa
nit(app/inbound): fix `InboundMetrics` doc comment (#4078)
this comment changes this comment in two ways:

1. fix a copy-paste typo. this should say "inbound", not "outbound".
2. add note that this is a "legacy" structure.

the equivalent structure in the outbound proxy was labeled as such
in https://github.com/linkerd/linkerd2-proxy/pull/2887.

see:

```rust
 /// Holds LEGACY outbound proxy metrics.
 #[derive(Clone, Debug)]
 pub struct OutboundMetrics {
     pub(crate) http_errors: error::Http,
     pub(crate) tcp_errors: error::Tcp,

     // pub(crate) http_route_backends: RouteBackendMetrics,
     // pub(crate) grpc_route_backends: RouteBackendMetrics,
     /// Holds metrics that are common to both inbound and outbound proxies. These metrics are
     /// reported separately
     pub(crate) proxy: Proxy,

     pub(crate) prom: PromMetrics,
 }
```

\- <dce6b61191/linkerd/app/outbound/src/metrics.rs (L22-L35)>

`authz::HttpAuthzMetrics`, `error::HttpErrorMetrics`,
`authz::TcpAuthzMetrics`, and `error::TcpErrorMetrics` all make use of
the "legacy" metrics implementation defined in `linkerd_metrics`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-08-18 14:01:37 -04:00
dependabot[bot] dce6b61191
build(deps): bump syn from 2.0.105 to 2.0.106 (#4077)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.105 to 2.0.106.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.105...2.0.106)

---
updated-dependencies:
- dependency-name: syn
  dependency-version: 2.0.106
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 12:12:30 -04:00
dependabot[bot] 28ebc47a6b
build(deps): bump cc from 1.2.32 to 1.2.33 (#4076)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.32 to 1.2.33.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.32...cc-v1.2.33)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.33
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 11:38:09 -04:00
dependabot[bot] 4bae7e98f2
build(deps): bump proc-macro2 from 1.0.97 to 1.0.101 (#4075)
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.97 to 1.0.101.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.97...1.0.101)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-version: 1.0.101
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 11:37:49 -04:00
dependabot[bot] b89c4902c6
build(deps): bump thiserror from 2.0.14 to 2.0.15 (#4074)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.14 to 2.0.15.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.14...2.0.15)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-version: 2.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 11:26:07 -04:00
dependabot[bot] 8a80f1ce95
build(deps): bump async-trait from 0.1.88 to 0.1.89 (#4073)
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.88 to 0.1.89.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.88...0.1.89)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-version: 0.1.89
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 10:47:36 -04:00
dependabot[bot] edc35d6e18
build(deps): bump derive_arbitrary from 1.4.1 to 1.4.2 (#4072)
Bumps [derive_arbitrary](https://github.com/rust-fuzz/arbitrary) from 1.4.1 to 1.4.2.
- [Changelog](https://github.com/rust-fuzz/arbitrary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/arbitrary/compare/v1.4.1...v1.4.2)

---
updated-dependencies:
- dependency-name: derive_arbitrary
  dependency-version: 1.4.2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 10:44:51 -04:00
dependabot[bot] 99f322a9a0
build(deps): bump arbitrary from 1.4.1 to 1.4.2 (#4071)
Bumps [arbitrary](https://github.com/rust-fuzz/arbitrary) from 1.4.1 to 1.4.2.
- [Changelog](https://github.com/rust-fuzz/arbitrary/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/arbitrary/compare/v1.4.1...v1.4.2)

---
updated-dependencies:
- dependency-name: arbitrary
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-18 07:26:46 -07:00
Scott Fleener 627a5aad21
feat(tls): Remove boring as a TLS implementation (#4038)
* chore(tls): Remove ring as crypto backend

The broader ecosystem has mostly moved to aws-lc-rs as the primary rustls backend, and we should follow suit. This will also simplify the maintenance of the proxy's TLS implementation in the long term.

There will need to be some refactoring to clean up the rustls provider interfaces, but that will come in follow-ups.

Signed-off-by: Scott Fleener <scott@buoyant.io>

* feat(tls): Remove boring as a TLS implementation

BoringSSL, as we use it today, doesn't integrate well with the broader rustls ecosystem, so this removes it. This will also simplify the maintenance of the proxy's TLS implementation in the long term.

There will need to be some refactoring to clean up the rustls provider interfaces, but that will come in follow-ups.

Signed-off-by: Scott Fleener <scott@buoyant.io>

* chore(tls): Restore existing aws-lc feature names for compatibility

Signed-off-by: Scott Fleener <scott@buoyant.io>

* fix(tls): Use correct feature name for fips conditionals

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-14 23:27:58 -04:00
Scott Fleener 356f80b786
chore(tls): Improve `aws-lc` usage (#4069)
This adds a few small improvements to how we handle the `aws-lc` usage in the proxy:

- Pull provider customization to the `aws-lc` backend, reducing the amount that the module exposes
- Validate that the provider is actually FIPS compatible when fips is enabled
- Use the same signature verification algorithms in the `rustls` provider as we do in the cert verifier. Previously, the provider also included RSA_PSS_2048_8192_SHA256, which is marked as legacy and we don't have a strong reason to support.
- Add change detector tests for the cipher suites, key exchange groups, and signature algorithms. These should ideally never change unless `rustls` changes, at which point we can re-evaluate which algorithms are in use by the proxy.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-14 18:56:35 +00:00
dependabot[bot] 0b3bc61263
build(deps): bump hashbrown from 0.15.2 to 0.15.5 (#4068)
Bumps [hashbrown](https://github.com/rust-lang/hashbrown) from 0.15.2 to 0.15.5.
- [Release notes](https://github.com/rust-lang/hashbrown/releases)
- [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/commits/v0.15.5)

---
updated-dependencies:
- dependency-name: hashbrown
  dependency-version: 0.15.5
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-14 11:30:16 -04:00
Scott Fleener 2b0e723027
chore(deps): Update tonic deps to 0.13 (#4066)
* chore(deps): Update tonic deps to 0.13

Signed-off-by: Scott Fleener <scott@buoyant.io>

* chore(deps): Update linkerd2-proxy-api to 0.17.0

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-13 10:45:42 -07:00
Scott Fleener 2156c3d5e3
chore(tls): Remove `ring` as `rustls` crypto backend (#4029)
* chore(tls): Remove ring as crypto backend

The broader ecosystem has mostly moved to aws-lc-rs as the primary rustls backend, and we should follow suit. This will also simplify the maintenance of the proxy's TLS implementation in the long term.

There will need to be some refactoring to clean up the rustls provider interfaces, but that will come in follow-ups.

Signed-off-by: Scott Fleener <scott@buoyant.io>

* chore(tls): Restore existing aws-lc feature names for compatibility

Signed-off-by: Scott Fleener <scott@buoyant.io>

* fix(tls): Use correct feature name for fips conditionals

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-13 13:13:57 -04:00
dependabot[bot] c4cae21e11
build(deps): bump syn from 2.0.104 to 2.0.105 (#4067)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.104 to 2.0.105.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.104...2.0.105)

---
updated-dependencies:
- dependency-name: syn
  dependency-version: 2.0.105
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-13 10:09:16 -07:00
Scott Fleener 89c88caf5c
chore(deps): Manually remove unused dependencies (#4065)
Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-13 10:44:43 -04:00
dependabot[bot] bb612d3aac
build(deps): bump the symbolic group with 2 updates (#4063)
Bumps the symbolic group with 2 updates: [symbolic-common](https://github.com/getsentry/symbolic) and [symbolic-demangle](https://github.com/getsentry/symbolic).


Updates `symbolic-common` from 12.16.1 to 12.16.2
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.16.1...12.16.2)

Updates `symbolic-demangle` from 12.16.1 to 12.16.2
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.16.1...12.16.2)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-version: 12.16.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: symbolic
- dependency-name: symbolic-demangle
  dependency-version: 12.16.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: symbolic
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 17:18:00 -07:00
dependabot[bot] 7030cc51ed
build(deps): bump anyhow from 1.0.98 to 1.0.99 (#4062)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.98 to 1.0.99.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.98...1.0.99)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-version: 1.0.99
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 18:39:04 +00:00
dependabot[bot] af520dfd12
build(deps): bump proc-macro2 from 1.0.96 to 1.0.97 (#4061)
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.96 to 1.0.97.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.96...1.0.97)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-version: 1.0.97
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 12:33:58 -04:00
dependabot[bot] ccf91dfb3e
build(deps): bump actions/checkout from 4.3.0 to 5.0.0 (#4060)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.3.0 to 5.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](08eba0b27e...08c6903cd8)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 16:18:00 +00:00
dependabot[bot] 69cd164da1
build(deps): bump thiserror from 2.0.12 to 2.0.14 (#4059)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.12 to 2.0.14.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.12...2.0.14)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-version: 2.0.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 15:56:38 +00:00
dependabot[bot] feb5f87713
build(deps): bump libc from 0.2.174 to 0.2.175 (#4057)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.174 to 0.2.175.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.175/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.174...0.2.175)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.175
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-11 12:14:04 -04:00
dependabot[bot] fdd7f218a3
build(deps): bump actions/checkout from 4.2.2 to 4.3.0 (#4053)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 4.3.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](11bd71901b...08eba0b27e)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-11 11:06:10 -04:00
dependabot[bot] b4e2b7e24f
build(deps): bump glob from 0.3.2 to 0.3.3 (#4055)
Bumps [glob](https://github.com/rust-lang/glob) from 0.3.2 to 0.3.3.
- [Release notes](https://github.com/rust-lang/glob/releases)
- [Changelog](https://github.com/rust-lang/glob/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/glob/compare/v0.3.2...v0.3.3)

---
updated-dependencies:
- dependency-name: glob
  dependency-version: 0.3.3
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-11 11:05:55 -04:00
dependabot[bot] 1b07f277d7
build(deps): bump rustversion from 1.0.21 to 1.0.22 (#4056)
Bumps [rustversion](https://github.com/dtolnay/rustversion) from 1.0.21 to 1.0.22.
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.21...1.0.22)

---
updated-dependencies:
- dependency-name: rustversion
  dependency-version: 1.0.22
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-11 11:05:34 -04:00
dependabot[bot] 25cf0c7f11
build(deps): bump proc-macro2 from 1.0.95 to 1.0.96 (#4054)
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.95 to 1.0.96.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.95...1.0.96)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-version: 1.0.96
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-11 14:52:05 +00:00
dependabot[bot] d46e7c0c82
build(deps): bump cc from 1.2.31 to 1.2.32 (#4051)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.31 to 1.2.32.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.31...cc-v1.2.32)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.32
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-08 13:28:21 -04:00
dependabot[bot] 3305a890b0
build(deps): bump slab from 0.4.10 to 0.4.11 (#4052)
Bumps [slab](https://github.com/tokio-rs/slab) from 0.4.10 to 0.4.11.
- [Release notes](https://github.com/tokio-rs/slab/releases)
- [Changelog](https://github.com/tokio-rs/slab/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/slab/compare/v0.4.10...v0.4.11)

---
updated-dependencies:
- dependency-name: slab
  dependency-version: 0.4.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-08 13:28:01 -04:00
katelyn martin d850fa6f73
refactor(metrics): introduce a `legacy` namespace (#4050)
`linkerd-metrics` contains a suite of facilities for defining,
registering, and serving Prometheus metrics. these predate the
[`prometheus-client`](https://crates.io/crates/prometheus-client/)
crate, which should now be used for our metrics.

`linkerd-metrics` defines a `prom` namespace, which reëxports symbols
from the `prometheus-client` library. as the documentation comment for
this submodule notes, this should be used for all new metrics.

6b323d8457/linkerd/metrics/src/lib.rs (L30-L60)

`linkerd-metrics` still provides its legacy types in the public surface
of this library today, which can make it difficult to differentiate
between our two metrics implementations.

this branch introduces a new `legacy` namespace, to help clarify the
distinction between these two Prometheus implementations, and to smooth
the road to further adoption of `prometheus-client` interfaces across
the proxy.

---

* refactor(metrics): introduce empty `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `Counter` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `Gauge` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `Histogram` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `Metric` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `FmtMetric` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `FmtMetrics` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `FmtLabels` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `LastUpdate` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `Store` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `SharedStore` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `Serve` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `NewMetrics` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor: move `Factor` into `legacy` namespace

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-08-07 15:33:17 -04:00
dependabot[bot] 6b323d8457
build(deps): bump governor from 0.10.0 to 0.10.1 (#4049)
Bumps [governor](https://github.com/boinkor-net/governor) from 0.10.0 to 0.10.1.
- [Release notes](https://github.com/boinkor-net/governor/releases)
- [Changelog](https://github.com/boinkor-net/governor/blob/master/release.toml)
- [Commits](https://github.com/boinkor-net/governor/compare/v0.10.0...v0.10.1)

---
updated-dependencies:
- dependency-name: governor
  dependency-version: 0.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-07 10:37:18 -04:00
dependabot[bot] 7f58cd56ed
build(deps): bump tokio-metrics from 0.4.3 to 0.4.4 (#4048)
Bumps [tokio-metrics](https://github.com/tokio-rs/tokio-metrics) from 0.4.3 to 0.4.4.
- [Release notes](https://github.com/tokio-rs/tokio-metrics/releases)
- [Changelog](https://github.com/tokio-rs/tokio-metrics/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/tokio-metrics/commits)

---
updated-dependencies:
- dependency-name: tokio-metrics
  dependency-version: 0.4.4
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-07 10:37:00 -04:00
Scott Fleener 43e3f630ec feat(tls): Include rustls crypto provider metrics
This includes a small set of metrics about the currently installed rustls crypto provider and the algorithms it is configured to use.

We don't have 100% assurance that a default crypto provider has been installed before registering the metric, but in local testing it never appeared to be a problem. When we refactor the rustls initialization we can add an extra guarantee that we've initialized it by this point.

Example metric:
```
# HELP rustls_info Proxy TLS info.
# TYPE rustls_info gauge
rustls_info{tls_suites="TLS13_AES_128_GCM_SHA256,TLS13_AES_256_GCM_SHA384,TLS13_CHACHA20_POLY1305_SHA256,",tls_kx_groups="X25519,secp256r1,secp384r1,X25519MLKEM768,",tls_rand="AwsLcRs",tls_key_provider="AwsLcRs",tls_fips="false"} 1
```

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-07 10:01:07 -04:00
Oliver Gould 7758436831
chore(ci): exercise all release platforms on workflow change (#4047)
We only build linux/amd64 during typical release CI runs. This means that the platform-
specific builds are not exercised. This change updates the release workflow so that
all platforms are built whenever the workflow itself is changed.
2025-08-06 14:29:05 +00:00
dependabot[bot] c0f921af33
build(deps): bump zerovec from 0.11.3 to 0.11.4 (#4046)
Bumps [zerovec](https://github.com/unicode-org/icu4x) from 0.11.3 to 0.11.4.
- [Release notes](https://github.com/unicode-org/icu4x/releases)
- [Changelog](https://github.com/unicode-org/icu4x/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unicode-org/icu4x/compare/ind/zerovec@0.11.3...ind/zerovec@0.11.4)

---
updated-dependencies:
- dependency-name: zerovec
  dependency-version: 0.11.4
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-06 09:48:31 -04:00
Scott Fleener b558ce5320
chore(meshtls-rustls): use aws-lc as the default crypto backend (#4043)
The broader ecosystem has mostly moved to `aws-lc-rs` as the primary `rustls` backend, and we should follow suit. This will also simplify the maintenance of the proxy's TLS implementation in the long term.

This requires some extra configuration for successful cross-compilation, ideally we can remove this extra configuration once linkerd/dev v48 is available.

This doesn't remove `ring` as a crypto backend, that can come in a follow-up at https://github.com/linkerd/linkerd2-proxy/pull/4029
2025-08-05 13:22:26 -07:00
dependabot[bot] 894d3506df
build(deps): bump socket2 from 0.5.10 to 0.6.0 (#4003)
* build(deps): bump socket2 from 0.5.10 to 0.6.0

Bumps [socket2](https://github.com/rust-lang/socket2) from 0.5.10 to 0.6.0.
- [Release notes](https://github.com/rust-lang/socket2/releases)
- [Changelog](https://github.com/rust-lang/socket2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/socket2/commits)

---
updated-dependencies:
- dependency-name: socket2
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(proxy/transport): use `original_dst_v*` methods

these have been renamed.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: katelyn martin <kate@buoyant.io>
2025-08-05 13:09:56 -07:00
dependabot[bot] 01e7ec0820
build(deps): bump zerovec from 0.11.2 to 0.11.3 (#4044)
Bumps [zerovec](https://github.com/unicode-org/icu4x) from 0.11.2 to 0.11.3.
- [Release notes](https://github.com/unicode-org/icu4x/releases)
- [Changelog](https://github.com/unicode-org/icu4x/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unicode-org/icu4x/commits/ind/zerovec@0.11.3)

---
updated-dependencies:
- dependency-name: zerovec
  dependency-version: 0.11.3
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-05 13:00:54 -07:00
dependabot[bot] 4f563fab68
build(deps): bump tokio-metrics from 0.4.2 to 0.4.3 (#3995)
Bumps [tokio-metrics](https://github.com/tokio-rs/tokio-metrics) from 0.4.2 to 0.4.3.
- [Release notes](https://github.com/tokio-rs/tokio-metrics/releases)
- [Changelog](https://github.com/tokio-rs/tokio-metrics/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/tokio-metrics/compare/v0.4.2...v0.4.3)

---
updated-dependencies:
- dependency-name: tokio-metrics
  dependency-version: 0.4.3
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-05 07:50:44 -07:00
dependabot[bot] 168c4bff7d
build(deps): bump tokio from 1.45.0 to 1.47.1 (#4040)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.45.0 to 1.47.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.45.0...tokio-1.47.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.47.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-05 09:44:53 -04:00
dependabot[bot] 0df8cdbedb
build(deps): bump cc from 1.2.30 to 1.2.31 (#4042)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.30 to 1.2.31.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.30...cc-v1.2.31)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.31
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-04 14:59:55 -07:00
dependabot[bot] 1b837b7f91
build(deps): bump tokio-util from 0.7.15 to 0.7.16 (#4041)
Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.15 to 0.7.16.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.15...tokio-util-0.7.16)

---
updated-dependencies:
- dependency-name: tokio-util
  dependency-version: 0.7.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-04 14:59:00 -07:00
katelyn martin 40078c96ca
chore(deps): update from tokio 1.45 to 1.47 (#4032)
* build(deps): bump tokio from 1.45.0 to 1.47.0

Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.45.0 to 1.47.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.45.0...tokio-1.47.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.47.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

---

chore(deny): ignore socket2@v0.5

there is now a v0.6 used by the latest tokio.

while we wait for this new version to propagate through the ecosystem,
allow for two socket2 dependencies.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/integration): remove inbound_io_err test

> @cratelyn I think it would be appropriate to remove these tests, given
> that they can no longer behave properly. I don't think that this test
> case is particularly meaningful or load bearing, it's best just to
> unblock the dependency updates.

\- <https://github.com/BuoyantIO/enterprise-linkerd/issues/1645#issuecomment-3046905516>

Co-authored-by: Oliver Gould <ver@buoyant.io>
Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/integration): remove inbound_multi test

this test exercises the same thing that the previous two tests do, as
the comment at the top of it points out.

this test is redundant, and we have removed the i/o error coverage that
this was redunant with. let's remove it.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-08-04 09:04:02 -07:00
dependabot[bot] 9eaf1425a7
build(deps): bump signal-hook-registry from 1.4.5 to 1.4.6 (#4039)
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.4.5 to 1.4.6.
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/registry-v1.4.5...registry-v1.4.6)

---
updated-dependencies:
- dependency-name: signal-hook-registry
  dependency-version: 1.4.6
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-04 08:08:41 -07:00
dependabot[bot] 842452368c
build(deps): bump rustc-demangle from 0.1.25 to 0.1.26 (#4026)
Bumps [rustc-demangle](https://github.com/rust-lang/rustc-demangle) from 0.1.25 to 0.1.26.
- [Release notes](https://github.com/rust-lang/rustc-demangle/releases)
- [Changelog](https://github.com/rust-lang/rustc-demangle/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/rustc-demangle/commits/rustc-demangle-v0.1.26)

---
updated-dependencies:
- dependency-name: rustc-demangle
  dependency-version: 0.1.26
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-04 11:07:17 -04:00
dependabot[bot] 09333dc2b2
build(deps): bump the symbolic group with 2 updates (#4035)
Bumps the symbolic group with 2 updates: [symbolic-common](https://github.com/getsentry/symbolic) and [symbolic-demangle](https://github.com/getsentry/symbolic).


Updates `symbolic-common` from 12.16.0 to 12.16.1
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.16.0...12.16.1)

Updates `symbolic-demangle` from 12.16.0 to 12.16.1
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.16.0...12.16.1)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-version: 12.16.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: symbolic
- dependency-name: symbolic-demangle
  dependency-version: 12.16.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: symbolic
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-08-01 18:28:55 +00:00
dependabot[bot] ddc847ccc4
build(deps): bump serde_json from 1.0.141 to 1.0.142 (#4036)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.141 to 1.0.142.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.141...v1.0.142)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-version: 1.0.142
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 11:23:49 -07:00
Scott Fleener 8d56746c1f
feat!(ci): Remove arm/v7 support (#4037)
This architecture has become too significant of a maintenance burden, and isn't used often enough to justify the associated maintenance cost.

This removes arm/v7 from all the build infrastructure/dockerfiles/etc. Note that arm64 targets are still widely used and well supported.

Related: https://github.com/linkerd/linkerd2/pull/14308

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-08-01 13:26:12 -04:00
dependabot[bot] db0ed46978
build(deps): bump rustls from 0.23.29 to 0.23.31 in the rustls group (#4034)
Bumps the rustls group with 1 update: [rustls](https://github.com/rustls/rustls).


Updates `rustls` from 0.23.29 to 0.23.31
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.29...v/0.23.31)

---
updated-dependencies:
- dependency-name: rustls
  dependency-version: 0.23.31
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: rustls
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 05:53:48 -07:00
katelyn martin 1d94082d4b
chore(deps): downgrade deranged from 0.4.1 to 0.4.0 (#4031)
- https://crates.io/crates/deranged/versions
- https://crates.io/crates/deranged/0.4.1

this version has been yanked. this commit addresses this cargo deny
warning:

```
warning[yanked]: detected yanked crate (try `cargo update -p deranged`)
   ┌─ /home/katie/linkerd/linkerd2-proxy/Cargo.lock:41:1
   │
41 │ deranged 0.4.1 registry+https://github.com/rust-lang/crates.io-index
   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ yanked version
   │
```

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-07-29 18:14:11 +00:00
dependabot[bot] 744e29e0bd
build(deps): bump rangemap from 1.5.1 to 1.6.0 (#4028)
Bumps [rangemap](https://github.com/jeffparsons/rangemap) from 1.5.1 to 1.6.0.
- [Changelog](https://github.com/jeffparsons/rangemap/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jeffparsons/rangemap/commits)

---
updated-dependencies:
- dependency-name: rangemap
  dependency-version: 1.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-29 10:59:35 -04:00
katelyn martin 83373d6b89
chore(deps): bump h2 from 0.4.8 to 0.4.11 (#4024)
- https://github.com/hyperium/h2/compare/v0.4.8...v0.4.11

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-07-28 21:23:25 +00:00
Scott Fleener 1dcb7a7d1a
fix(rustls): Make `ring` and `aws-lc-rs` exclusive features (#4009)
Currently, disabling the `ring` feature does not actually disable the dependency across the tree. Doing so requires a couple of tightly coupled steps:

- Making `ring` and `aws-lc` exclusive features, raising a compile error if they are both enabled.
- Removing a direct dependency on some `ring` types, and instead going through `rustls` for equivalent functionality.
- Removing a direct dependency on the `ring` crypto provider for integration tests, and instead using the provider from `linkerd-meshtls`.
- Installing the default crypto provider globally for the process and re-using it when requested, mostly to make the tests pass.

This was tested using a temporary `cargo deny` config that forbid `ring` when `aws-lc-rs` was used, and vice-versa. Note that it doesn't completely remove ring for dev dependencies, but that can be done as a follow-up.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-07-28 15:28:47 -04:00
Scott Fleener 68a6b6d1e8
fix(tls): Update preferred cipher suite order (#4015)
This makes two changes to the preferred cipher suite order.
- Prefer AES algorithms over ChaCha20. AES is significantly faster when AES hardware is present, and AES hardware is on all x86 CPUs since ~2010, and all ARM server CPUs for a similar amount of time. For these reasons it's reasonable to default to AES for modern deployments, and it's the same default that `aws-lc-rs` makes anyway.
- Remove ChaCha20 when FIPS is enabled. It's no longer a supported algorithm, so we shouldn't have it as an option.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-07-28 15:05:05 -04:00
Oliver Gould cdbb55fd53
build(linkerd2-proxy): make release artifacts auditable (#4023)
Auditing tools like Syft cannot inspect proxy dependencies, which makes it difficult to inspect the state of a binary. This change updates the release process to use cargo-auditable, which documents the proxy's crate dependencies in its release binary.
2025-07-28 17:00:06 +00:00
Oliver Gould 5997453393
build(deps): update linkerd/dev to v47 (#4022) 2025-07-28 11:49:06 -05:00
Joe 10643b9525
updating metrics descriptions (#4020)
Signed-off-by: Joe F <joe@buoyant.io>
2025-07-25 20:08:56 +00:00
dependabot[bot] fd0ea24b87
build(deps): bump serde_json from 1.0.140 to 1.0.141 (#4021)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.140 to 1.0.141.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.140...v1.0.141)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-version: 1.0.141
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-25 16:07:16 -04:00
dependabot[bot] 3a159be91a
build(deps): bump prettyplease from 0.2.35 to 0.2.36 (#4018)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.35 to 0.2.36.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.35...0.2.36)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-version: 0.2.36
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 10:03:57 -04:00
dependabot[bot] b3bc6fe8cd
build(deps): bump hyper-util from 0.1.15 to 0.1.16 (#4019)
Bumps [hyper-util](https://github.com/hyperium/hyper-util) from 0.1.15 to 0.1.16.
- [Release notes](https://github.com/hyperium/hyper-util/releases)
- [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.15...v0.1.16)

---
updated-dependencies:
- dependency-name: hyper-util
  dependency-version: 0.1.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 10:02:38 -04:00
dependabot[bot] 5a00b70d11
build(deps): bump aws-lc-rs from 1.13.2 to 1.13.3 (#4016)
Bumps [aws-lc-rs](https://github.com/aws/aws-lc-rs) from 1.13.2 to 1.13.3.
- [Release notes](https://github.com/aws/aws-lc-rs/releases)
- [Commits](https://github.com/aws/aws-lc-rs/compare/v1.13.2...v1.13.3)

---
updated-dependencies:
- dependency-name: aws-lc-rs
  dependency-version: 1.13.3
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 07:02:52 -07:00
dependabot[bot] b91dd3e7af
build(deps): bump rcgen from 0.14.2 to 0.14.3 (#4017)
Bumps [rcgen](https://github.com/rustls/rcgen) from 0.14.2 to 0.14.3.
- [Release notes](https://github.com/rustls/rcgen/releases)
- [Commits](https://github.com/rustls/rcgen/compare/v0.14.2...v0.14.3)

---
updated-dependencies:
- dependency-name: rcgen
  dependency-version: 0.14.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 07:02:25 -07:00
dependabot[bot] a699b1cf58
build(deps): bump cc from 1.2.29 to 1.2.30 (#4014)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.29 to 1.2.30.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.29...cc-v1.2.30)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.30
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 09:35:32 -04:00
dependabot[bot] 9f3c45874e
build(deps): bump rand from 0.9.1 to 0.9.2 (#4013)
Bumps [rand](https://github.com/rust-random/rand) from 0.9.1 to 0.9.2.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/rand_core-0.9.1...rand_core-0.9.2)

---
updated-dependencies:
- dependency-name: rand
  dependency-version: 0.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 09:35:19 -04:00
Oliver Gould 1de179e178
chore(deps): update jemallocator 0.5 to tikv-jemallocator 0.6 (#4012)
tikv-jemallocator supersedes jemallocator. To enable jemalloc profiling, this change updates the dependency and adds a `jemalloc-profiling` feature so that profiling can be enabled at build time.
2025-07-18 17:42:41 -04:00
dependabot[bot] f9d7e08242
build(deps): bump the rustls group with 2 updates (#4010)
---
updated-dependencies:
- dependency-name: rustls-webpki
  dependency-version: 0.103.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rustls
- dependency-name: rustls
  dependency-version: 0.23.29
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: rustls
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 07:48:31 -07:00
dependabot[bot] bd454b4be8
build(deps): bump the symbolic group with 2 updates (#4011)
---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-version: 12.16.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: symbolic
- dependency-name: symbolic-demangle
  dependency-version: 12.16.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: symbolic
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 07:48:06 -07:00
Oliver Gould b1f8fa5419
chore(ci): enable overriding the runner in workflows (#4008)
We use the ubuntu-24.04 runner by default, but in forks this may not be appropriate. This change updates the runners to support overriding via the LINKERD2_PROXY_RUNNER variable.
2025-07-17 17:22:42 -07:00
dependabot[bot] e04947610a
build(deps): bump aws-lc-rs from 1.13.1 to 1.13.2 (#4006)
---
updated-dependencies:
- dependency-name: aws-lc-rs
  dependency-version: 1.13.2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-17 11:05:10 -07:00
Oliver Gould 9c48e2471e
fix(app/env): limit default inbound connection pool size (#4007)
The inbound connection pool is effectively unlimited. This change configures a
default limit of 10K.
2025-07-17 16:47:32 +00:00
dependabot[bot] df38a5a2c9
build(deps): bump the rustls group across 1 directory with 3 updates (#3908)
* build(deps): bump the rustls group across 1 directory with 3 updates

Bumps the rustls group with 3 updates in the / directory: [rustls-webpki](https://github.com/rustls/webpki), [rustls](https://github.com/rustls/rustls) and [rustls-pki-types](https://github.com/rustls/pki-types).


Updates `rustls-webpki` from 0.103.1 to 0.103.2
- [Release notes](https://github.com/rustls/webpki/releases)
- [Commits](https://github.com/rustls/webpki/compare/v/0.103.1...v/0.103.2)

Updates `rustls` from 0.23.26 to 0.23.27
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.26...v/0.23.27)

Updates `rustls-pki-types` from 1.11.0 to 1.12.0
- [Release notes](https://github.com/rustls/pki-types/releases)
- [Commits](https://github.com/rustls/pki-types/compare/v/1.11.0...v/1.12.0)

---
updated-dependencies:
- dependency-name: rustls-webpki
  dependency-version: 0.103.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rustls
- dependency-name: rustls
  dependency-version: 0.23.27
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: rustls
- dependency-name: rustls-pki-types
  dependency-version: 1.12.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: rustls
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(rustls): Remove dependency on most rustls internal types

We only used these types for generating a ClientHello message for testing. Instead, we can manually encode a sample message based on the TLS spec.

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Scott Fleener <scott@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Scott Fleener <scott@buoyant.io>
2025-07-17 16:20:37 +00:00
dependabot[bot] 7c6882bb35
build(deps): bump rcgen from 0.13.2 to 0.14.2 (#4000)
* build(deps): bump rcgen from 0.13.2 to 0.14.2

Bumps [rcgen](https://github.com/rustls/rcgen) from 0.13.2 to 0.14.2.
- [Release notes](https://github.com/rustls/rcgen/releases)
- [Commits](https://github.com/rustls/rcgen/compare/v0.13.2...v0.14.2)

---
updated-dependencies:
- dependency-name: rcgen
  dependency-version: 0.14.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(test): Fix breaking changes from rcgen 0.14

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Scott Fleener <scott@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Scott Fleener <scott@buoyant.io>
2025-07-16 19:34:47 -04:00
katelyn martin a6e47d7e03
fix(app/env): a lower default maximum per-host connection limit (#4005)
* chore(app/env): fix typo

Signed-off-by: katelyn martin <kate@buoyant.io>

* fix(app/env): a lower default maximum per-host connection limit

see also:
* #4004
* linkerd/linkerd2#14204

in #4004 we fixed an issue related to our HTTP/1.1 client's connection
pool.

this further hedges against future issues related to our HTTP client
exhausting resources available to its container. today, the limit by
default is `usize::MAX`, which is dramatically higher than the practical
limit.

this commit changes the limit for outbound idle connections per-host to
10,000.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-07-15 13:01:54 -04:00
Oliver Gould 2cc8c7d80e
fix(proxy/http): fix HTTP/1 client idle timeouts (#4004)
When constructing the HTTP/1 client, we configure connection pooling, but
notably do not provide a timer implementation to Hyper. This causes hyper's
connection pool to be configured without idle timeouts, which may lead to
resource leaks, especially for clients that communicate with many virtual hosts.

This change updates the HTTP/1 client builder to use a Tokio timer, which allows
Hyper to manage idle timeouts correctly.
2025-07-14 14:56:35 -07:00
dependabot[bot] 21f3ffc6c1
build(deps): bump crc32fast from 1.4.2 to 1.5.0 (#4002)
Bumps [crc32fast](https://github.com/srijs/rust-crc32fast) from 1.4.2 to 1.5.0.
- [Commits](https://github.com/srijs/rust-crc32fast/compare/v1.4.2...v1.5.0)

---
updated-dependencies:
- dependency-name: crc32fast
  dependency-version: 1.5.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 11:49:32 -04:00
dependabot[bot] 1b85cf93a4
build(deps): bump memmap2 from 0.9.5 to 0.9.7 (#4001)
Bumps [memmap2](https://github.com/RazrFalcon/memmap2-rs) from 0.9.5 to 0.9.7.
- [Changelog](https://github.com/RazrFalcon/memmap2-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/RazrFalcon/memmap2-rs/commits)

---
updated-dependencies:
- dependency-name: memmap2
  dependency-version: 0.9.7
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 07:02:56 -07:00
dependabot[bot] ce5df7d026
build(deps): bump cc from 1.2.27 to 1.2.29 (#3999)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.27 to 1.2.29.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.27...cc-v1.2.29)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.29
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-11 15:17:08 -04:00
Scott Fleener 79e612c2f9
feat(meshtls): Include AES_256_GCM as a supported ciphersuite (#3991)
This is a strong ciphersuite that's reasonable to include as a supported option. We still prefer CHACHA20_POLY1305 in non-FIPS modes for its speed, as well as keeping CHACHA20_POLY1305 as a backup for older proxies that only support it.

Signed-off-by: Scott Fleener <scott@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-07-10 15:23:47 -04:00
Oliver Gould 62ed64ea05
chore(build): bump linkerd/dev to v46 (#3984)
* Rust 1.88
2025-07-10 14:15:24 -04:00
dependabot[bot] e8de6359a5
build(deps): bump hyper-util from 0.1.14 to 0.1.15 (#3997)
Bumps [hyper-util](https://github.com/hyperium/hyper-util) from 0.1.14 to 0.1.15.
- [Release notes](https://github.com/hyperium/hyper-util/releases)
- [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.14...v0.1.15)

---
updated-dependencies:
- dependency-name: hyper-util
  dependency-version: 0.1.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 12:50:50 -04:00
dependabot[bot] 53a17808a7
build(deps): bump libfuzzer-sys from 0.4.9 to 0.4.10 (#3994)
Bumps [libfuzzer-sys](https://github.com/rust-fuzz/libfuzzer) from 0.4.9 to 0.4.10.
- [Changelog](https://github.com/rust-fuzz/libfuzzer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/libfuzzer/compare/0.4.9...0.4.10)

---
updated-dependencies:
- dependency-name: libfuzzer-sys
  dependency-version: 0.4.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 09:17:27 -04:00
katelyn martin 34b46ab6cd
refactor: `FmtLabels` impls use exhaustive bindings (#3988)
this is based on #3987.

in #3987 (_see https://github.com/linkerd/linkerd2/issues/13821_) we discovered that some of the types that implement [`FmtLabels`](085be9978d/linkerd/metrics/src/fmt.rs (L5)) could collide when used in registry keys; i.e., they might emit identical label sets, but distinct `Hash` values.

#3987 solves two bugs. this pull request proposes a follow-on change, introducing _exhaustive_ bindings to implementations of `FmtLabels`, to prevent this category of bug from reoccurring again in the future.

this change means that the introduction of an additional field to any of these label structures, e.g. `OutboundEndpointLabels` or `HTTPLocalRateLimitLabels`, will cause a compilation error unless said new field is handled in the corresponding `FmtLabels` implementation.

### 🔖 a note

in writing this pull request, i noticed one label that i believe is unintentionally being elided. i've refrained from changing behavior in this pull request. i do note it though, as an example of this syntax identifying the category of bug i hope to hedge against here.

---

* fix: do not key transport metrics registry on `ClientTls`

Signed-off-by: katelyn martin <kate@buoyant.io>

* fix: do not key transport metrics registry on `ServerTls`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(transport-metrics): exhaustive `Eos: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `ServerLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `TlsAccept: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `TargetAddr: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(metrics): exhaustive `Label: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/metrics): exhaustive `Status: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `ControlLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `ProfileRouteLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `InboundEndpointLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `ServerLabel: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `ServerAuthzLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `RouteLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `RouteAuthzLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `OutboundEndpointLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `Authority: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): exhaustive `StackLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/inbound): exhaustive `HTTPLocalRateLimitLabels: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/inbound): exhaustive `Key<L>: FmtLabels`

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(metrics): remove redundant banner comment

these impl blocks are all `FmtLabels`, following another series of the
same, above. we don't need another one of these comments.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(metrics): exhaustive `AndThen: FmtMetrics`

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(app/core): note unused label

see #3262 (618838ec7), which introduced this label.

to preserve behavior, this label remains unused.

X-Ref: #3262
Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-07-03 11:56:14 -04:00
Oliver Gould 288fc74800
chore(app): increase default max backoff durations (#3992)
The inbound and outbound connect backoffs are now set at 500ms. This is very aggressive in practice, especially when an endpoint remains unavailable.

This change increases the maximum backoff durations:

* inbound: 10s
* outbound: 60s

The default minimum backoff durations remain unchanged at 100ms so that failed
connections are retried quickly. This change only increases the default _maximum_ backoff so that the timeout increases substantially when an endpoint is unavailable for a longer period of time.
2025-07-02 18:52:53 -07:00
katelyn martin 030fa28d55
fix: remove ambiguous metrics registry keys (#3987)
### 🖼️ background

the linkerd2 proxy implements, registers, and exports Prometheus metrics using a variety of systems, for historical reasons. new metrics broadly rely upon the official [`prometheus-client`](https://github.com/prometheus/client_rust/) library, whose interfaces are reexported for internal consumption in the [`linkerd_metrics::prom`](https://github.com/linkerd/linkerd2-proxy/blob/main/linkerd/metrics/src/lib.rs#L30-L60) namespace.

other metrics predate this library however, and rely on the metrics registry implemented in the workspace's [`linkerd-metrics`](https://github.com/linkerd/linkerd2-proxy/tree/main/linkerd/metrics) library.

### 🐛 bug report

* https://github.com/linkerd/linkerd2/issues/13821

linkerd/linkerd2#13821 reported a bug in which duplicate metrics could be observed and subsequently dropped by Prometheus when upgrading the control plane via helm with an existing workload running.

### 🦋 reproduction example

for posterity, i'll note the reproduction steps here.

i used these steps to identify the `2025.3.2` edge release as the affected release. upgrading from `2025.2.3` to `2025.3.1` did not exhibit this behavior. see below for more discussion about the cause.

generate certificates via <https://linkerd.io/2.18/tasks/generate-certificates/>

using these two deployments, courtesy of @GTRekter:

<details>
<summary>**💾 click to expand: app deployment**</summary>

```yaml
apiVersion: v1 
kind: Namespace 
metadata: 
  name: simple-app 
  annotations: 
    linkerd.io/inject: enabled 
---
apiVersion: v1 
kind: Service 
metadata: 
  name: simple-app-v1 
  namespace: simple-app 
spec: 
  selector: 
    app: simple-app-v1 
    version: v1 
  ports: 
    - port: 80 
      targetPort: 5678
---
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: simple-app-v1 
  namespace: simple-app 
spec: 
  replicas: 1 
  selector: 
    matchLabels: 
      app: simple-app-v1 
      version: v1 
  template: 
    metadata: 
      labels: 
        app: simple-app-v1 
        version: v1 
    spec: 
      containers: 
        - name: http-app 
          image: hashicorp/http-echo:latest 
          args: 
            - "-text=Simple App v1" 
          ports: 
            - containerPort: 5678 
```
</details>

<details>
<summary>**🤠 click to expand: client deployment**</summary>

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: traffic
  namespace: simple-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: traffic
  template:
    metadata:
      labels:
        app: traffic
    spec:
      containers:
      - name: traffic
        image: curlimages/curl:latest
        command:
          - /bin/sh
          - -c
          - |
            while true; do
              TIMESTAMP_SEND=$(date '+%Y-%m-%d %H:%M:%S')
              PAYLOAD="{\"timestamp\":\"$TIMESTAMP_SEND\",\"test_id\":\"sniff_me\",\"message\":\"hello-world\"}"
              echo "$TIMESTAMP_SEND - Sending payload: $PAYLOAD"
              RESPONSE=$(curl -s -X POST \
                -H "Content-Type: application/json" \
                -d "$PAYLOAD" \
                http://simple-app-v1.simple-app.svc.cluster.local:80)
              TIMESTAMP_RESPONSE=$(date '+%Y-%m-%d %H:%M:%S')
              echo "$TIMESTAMP_RESPONSE - RESPONSE: $RESPONSE"
              sleep 1
            done
```
</details>

and this prometheus configuration:

<details>
<summary>**🔥 click to expand: prometheus configuration**</summary>

```yaml
global:
  scrape_interval: 10s

scrape_configs:
  - job_name: 'pod'
    scrape_interval: 10s
    static_configs:
    - targets: ['localhost:4191']
      labels:
        group: 'traffic'
```
</details>

we will perform the following steps:

```sh
# install the edge release

# specify the versions we'll migrate between.
export FROM="2025.3.1"
export TO="2025.3.2"

# create a cluster, and add the helm charts.
kind create cluster
helm repo add linkerd-edge https://helm.linkerd.io/edge

# install linkerd's crd's and control plane.
helm install linkerd-crds linkerd-edge/linkerd-crds \
  -n linkerd --create-namespace --version $FROM

helm install linkerd-control-plane \
  -n linkerd \
  --set-file identityTrustAnchorsPEM=cert/ca.crt \
  --set-file identity.issuer.tls.crtPEM=cert/issuer.crt \
  --set-file identity.issuer.tls.keyPEM=cert/issuer.key \
  --version $FROM \
  linkerd-edge/linkerd-control-plane

# install a simple app and a client to drive traffic.
kubectl apply -f duplicate-metrics-simple-app.yml
kubectl apply -f duplicate-metrics-traffic.yml

# bind the traffic pod's metrics port to the host.
kubectl port-forward -n simple-app deploy/traffic 4191

# start prometheus, begin scraping metrics
prometheus --config.file=prometheus.yml
```

now, open a browser and query `irate(request_total[1m])`.

next, upgrade the control plane:

```
helm upgrade linkerd-crds linkerd-edge/linkerd-crds \
  -n linkerd --create-namespace --version $TO
helm upgrade linkerd-control-plane \
  -n linkerd \
  --set-file identityTrustAnchorsPEM=cert/ca.crt \
  --set-file identity.issuer.tls.crtPEM=cert/issuer.crt \
  --set-file identity.issuer.tls.keyPEM=cert/issuer.key \
  --version $TO \
  linkerd-edge/linkerd-control-plane
```

prometheus will begin emitting warnings regarding 34 time series being dropped.

in your browser, querying `irate(request_total[1m])` once more will show that
the rate of requests has stopped, due to the new time series being dropped.

next, restart the workloads...

```
kubectl rollout restart deployment -n simple-app simple-app-v1 traffic
```

prometheus warnings will go away, as reported in linkerd/linkerd2#13821.

### 🔍 related changes

* https://github.com/linkerd/linkerd2/pull/13699
* https://github.com/linkerd/linkerd2/pull/13715

in linkerd/linkerd2#13715 and linkerd/linkerd2##13699, we made some changes to the destination controller. from the "Cautions" section of the `2025.3.2` edge release:

> Additionally, this release changes the default for `outbound-transport-mode`
> to `transport-header`, which will result in all traffic between meshed
> proxies flowing on port 4143, rather than using the original destination
> port.

linkerd/linkerd2#13699 (_included in `edge-25.3.1`_) introduced this outbound transport-protocol configuration surface, but maintained the default behavior, while linkerd/linkerd2#13715 (_included in `edge-25.3.2`_) altered the default behavior to route meshed traffic via port 4143.

this is a visible change in behavior that can be observed when upgrading from a version that preceded this change to the mesh. this means that when upgrading across `edge-25.3.2`, such as from the `2025.2.1` to `2025.3.2` versions of the helm charts, or from the `2025.2.3` to the `2025.3.4` versions of the helm charts (_reported upstream in linkerd/linkerd2#13821_), the freshly upgraded destination controller pods will begin routing meshed traffic differently.

i'll state explicitly, _that_ is not a bug! it is, however, an important clue to bear in mind: data plane pods that were started with the previous control plane version, and continue running after the control plane upgrade, will have seen both routing patterns. reporting a duplicate time series for affected metrics indicates that there is a hashing collision in our metrics system.

### 🐛 the bug(s)

we define a collection to structures to model labels for inbound and outbound endpoints'
metrics:

```rust
// linkerd/app/core/src/metrics.rs

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum EndpointLabels {
    Inbound(InboundEndpointLabels),
    Outbound(OutboundEndpointLabels),
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct InboundEndpointLabels {
    pub tls: tls::ConditionalServerTls,
    pub authority: Option<http::uri::Authority>,
    pub target_addr: SocketAddr,
    pub policy: RouteAuthzLabels,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct OutboundEndpointLabels {
    pub server_id: tls::ConditionalClientTls,
    pub authority: Option<http::uri::Authority>,
    pub labels: Option<String>,
    pub zone_locality: OutboundZoneLocality,
    pub target_addr: SocketAddr,
}
```

\- <https://github.com/linkerd/linkerd2-proxy/blob/main/linkerd/app/core/src/metrics.rs>

bear particular attention to the derived `Hash` implementation. note the `tls::ConditionalClientTls` and `tls::ConditionalServerTls` types used in each of these labels. these are used by some of our types like `TlsConnect` to emit prometheus labels, using our legacy system's `FmtLabels` trait:

```rust
// linkerd/app/core/src/transport/labels.rs

impl FmtLabels for TlsConnect<'_> {
    fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.0 {
            Conditional::None(tls::NoClientTls::Disabled) => {
                write!(f, "tls=\"disabled\"")
            }
            Conditional::None(why) => {
                write!(f, "tls=\"no_identity\",no_tls_reason=\"{}\"", why)
            }
            Conditional::Some(tls::ClientTls { server_id, .. }) => {
                write!(f, "tls=\"true\",server_id=\"{}\"", server_id)
            }
        }
    }
}
```

\- <99316f7898/linkerd/app/core/src/transport/labels.rs (L151-L165)>

note the `ClientTls` case, which ignores fields in the client tls information:

```rust
// linkerd/tls/src/client.rs

/// A stack parameter that configures a `Client` to establish a TLS connection.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ClientTls {
    pub server_name: ServerName,
    pub server_id: ServerId,
    pub alpn: Option<AlpnProtocols>,
}
```

\- <99316f7898/linkerd/tls/src/client.rs (L20-L26)>

this means that there is potential for an identical set of labels to be emitted given two `ClientTls` structures with distinct server names or ALPN protocols. for brevity, i'll elide the equivalent issue with `ServerTls`, and its corresponding `TlsAccept<'_>` label implementation, though it exhibits the same issue.

### 🔨 the fix

this pull request introduces two new types: `ClientTlsLabels` and `ServerTlsLabels`. these continue to implement `Hash`, for use as a key in our metrics registry, and for use in formatting labels.

`ClientTlsLabels` and `ServerTlsLabels` each resemble `ClientTls` and `ServerTls`, respectively, but do not contain any fields that are elided in label formatting, to prevent duplicate metrics from being emitted.

relatedly, #3988 audits our existing `FmtLabels` implementations and makes use of exhaustive bindings, to prevent this category of problem in the short-term future. ideally, we might eventually consider replacing the metrics interfaces in `linkerd-metrics`, but that is strictly kept out-of-scope for the purposes of this particular fix.

---

* fix: do not key transport metrics registry on `ClientTls`

Signed-off-by: katelyn martin <kate@buoyant.io>

* fix: do not key transport metrics registry on `ServerTls`

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-07-02 12:38:04 -04:00
dependabot[bot] 085be9978d
build(deps): bump indexmap from 2.9.0 to 2.10.0 (#3986)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.9.0 to 2.10.0.
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.9.0...2.10.0)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-version: 2.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-27 11:19:12 -04:00
dependabot[bot] 682421c98a
build(deps): bump Swatinem/rust-cache from 2.7.8 to 2.8.0 (#3983)
Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.7.8 to 2.8.0.
- [Release notes](https://github.com/swatinem/rust-cache/releases)
- [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md)
- [Commits](9d47c6ad4b...98c8021b55)

---
updated-dependencies:
- dependency-name: Swatinem/rust-cache
  dependency-version: 2.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-26 12:25:06 -04:00
katelyn martin 2b1e3925d5
fix(proxy/http): remove http/1 header read timeout (#3985)
this fixes #14131. this relates to #14147, though it does not introduce
a configurable option for this timeout.

 ###  background

in hyper 0.14, http/1.1 connections had no default header read timeout.
per the documentation for
[`hyper::server::Builder::http1_header_read_timeout()`][read-timeout-previous]:

> Set a timeout for reading client request headers. If a client does not
transmit the entire header within this time, the connection is closed.
>
> Default is None.

compare this with the latest hyper release, which enforces a
30 second timeout for http/1.1 connections. per the documentation for
[`hyper::server::conn::http1::Builder::header_read_timeout`][read-timeout-current]:

> Set a timeout for reading client request headers. If a client does not
> transmit the entire header within this time, the connection is closed.
>
> Requires a
> [Timer](https://docs.rs/hyper/latest/hyper/rt/trait.Timer.html) set by
> [Builder::timer](https://docs.rs/hyper/latest/hyper/server/conn/http1/struct.Builder.html#method.timer)
> to take effect. Panics if header_read_timeout is configured without a
> [Timer](https://docs.rs/hyper/latest/hyper/rt/trait.Timer.html).
>
> Pass None to disable.
>
> Default is 30 seconds.

this was changed in hyperium/hyper#3395, which was included in [the v1.0
release][v1-changelog].

[read-timeout-previous]: https://docs.rs/hyper/0.14.31/hyper/server/struct.Builder.html#method.http1_header_read_timeout
[read-timeout-current]: https://docs.rs/hyper/latest/hyper/server/conn/http1/struct.Builder.html#method.header_read_timeout
[v1-changelog]: https://github.com/hyperium/hyper/blob/master/CHANGELOG.md#v100-2023-11-15

 ### 🔨 changes

this commit passes `None` to the `linkerd-proxy-http::server::ServeHttp`
type's http/1 server-side connection builder, to remove the header read
timeout.

this restores the behavior that existed prior to linkerd/linkerd2#8733,
which upgraded our hyper dependency from 0.14 to 1.0.

X-Ref: https://github.com/linkerd/linkerd2/issues/14147
X-Ref: https://github.com/linkerd/linkerd2/issues/14131
X-Ref: https://github.com/linkerd/linkerd2/issues/8733
X-Ref: https://github.com/hyperium/hyper/issues/3395

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-06-26 12:08:38 -04:00
dependabot[bot] 504581e1d7
build(deps): bump bumpalo from 3.18.1 to 3.19.0 (#3982)
Bumps [bumpalo](https://github.com/fitzgen/bumpalo) from 3.18.1 to 3.19.0.
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/commits)

---
updated-dependencies:
- dependency-name: bumpalo
  dependency-version: 3.19.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-25 08:32:25 -04:00
Zahari Dichev 2869076d58
identity(spire): provide named pipe support for spire (#3970)
This change does two things: 
- adds support for `NamedPipes` to our SPIRE client. This will allow the client to connect to spire agents running on Windows hosts
- renames the `LINKERD2_PROXY_IDENTITY_SPIRE_SOCKET` to `LINKERD2_PROXY_IDENTITY_SPIRE_WORKLOAD_API_ADDRESS` and deprecates the former.

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2025-06-25 11:01:45 +03:00
dependabot[bot] 99316f7898
build(deps): bump prettyplease from 0.2.34 to 0.2.35 (#3981)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.34 to 0.2.35.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.34...0.2.35)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-version: 0.2.35
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-24 09:17:31 -04:00
dependabot[bot] 7255530037
build(deps): bump syn from 2.0.103 to 2.0.104 (#3980)
---
updated-dependencies:
- dependency-name: syn
  dependency-version: 2.0.104
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-23 08:04:23 -04:00
Oliver Gould 3fe2dee32e
fix(errno): comment typo (#3949) 2025-06-20 15:00:10 +00:00
dependabot[bot] 3590892686
build(deps): bump errno from 0.3.12 to 0.3.13 (#3979)
Bumps [errno](https://github.com/lambda-fairy/rust-errno) from 0.3.12 to 0.3.13.
- [Release notes](https://github.com/lambda-fairy/rust-errno/releases)
- [Changelog](https://github.com/lambda-fairy/rust-errno/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lambda-fairy/rust-errno/compare/v0.3.12...v0.3.13)

---
updated-dependencies:
- dependency-name: errno
  dependency-version: 0.3.13
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-20 10:09:16 -04:00
dependabot[bot] 80a216892d
build(deps): bump syn from 2.0.102 to 2.0.103 (#3978)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.102 to 2.0.103.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.102...2.0.103)

---
updated-dependencies:
- dependency-name: syn
  dependency-version: 2.0.103
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-20 10:09:07 -04:00
dependabot[bot] 4dc6353d0c
build(deps): bump autocfg from 1.4.0 to 1.5.0 (#3977)
Bumps [autocfg](https://github.com/cuviper/autocfg) from 1.4.0 to 1.5.0.
- [Commits](https://github.com/cuviper/autocfg/compare/1.4.0...1.5.0)

---
updated-dependencies:
- dependency-name: autocfg
  dependency-version: 1.5.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-20 09:58:37 -04:00
dependabot[bot] c325f526af
build(deps): bump slab from 0.4.9 to 0.4.10 (#3976)
Bumps [slab](https://github.com/tokio-rs/slab) from 0.4.9 to 0.4.10.
- [Release notes](https://github.com/tokio-rs/slab/releases)
- [Changelog](https://github.com/tokio-rs/slab/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/slab/compare/v0.4.9...v0.4.10)

---
updated-dependencies:
- dependency-name: slab
  dependency-version: 0.4.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-18 07:52:57 -04:00
dependabot[bot] 9b3d93ddf6
build(deps): bump libc from 0.2.173 to 0.2.174 (#3975)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.173 to 0.2.174.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.174/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.173...0.2.174)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.174
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-18 07:51:52 -04:00
dependabot[bot] dcd34222a9
build(deps): bump tracing-attributes in the tracing group (#3974)
Bumps the tracing group with 1 update: [tracing-attributes](https://github.com/tokio-rs/tracing).


Updates `tracing-attributes` from 0.1.29 to 0.1.30
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-attributes-0.1.29...tracing-attributes-0.1.30)

---
updated-dependencies:
- dependency-name: tracing-attributes
  dependency-version: 0.1.30
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: tracing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-18 07:51:26 -04:00
dependabot[bot] 8203cd2e96
build(deps): bump jiff from 0.2.14 to 0.2.15 (#3973)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.14 to 0.2.15.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.14...jiff-static-0.2.15)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-17 12:12:22 -04:00
dependabot[bot] 19235e0841
build(deps): bump libc from 0.2.172 to 0.2.173 (#3972)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.172 to 0.2.173.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.173/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.172...0.2.173)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.173
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-17 12:12:08 -04:00
dependabot[bot] 6f51389717
build(deps): bump thread_local from 1.1.8 to 1.1.9 (#3971)
Bumps [thread_local](https://github.com/Amanieu/thread_local-rs) from 1.1.8 to 1.1.9.
- [Release notes](https://github.com/Amanieu/thread_local-rs/releases)
- [Changelog](https://github.com/Amanieu/thread_local-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/thread_local-rs/compare/1.1.8...v1.1.9)

---
updated-dependencies:
- dependency-name: thread_local
  dependency-version: 1.1.9
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-17 12:11:57 -04:00
dependabot[bot] 3c2854beb1
build(deps): bump aws-lc-fips-sys from 0.13.6 to 0.13.7 (#3968)
Bumps [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) from 0.13.6 to 0.13.7.
- [Release notes](https://github.com/aws/aws-lc-rs/releases)
- [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.13.6...aws-lc-fips-sys/v0.13.7)

---
updated-dependencies:
- dependency-name: aws-lc-fips-sys
  dependency-version: 0.13.7
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-16 12:26:15 -04:00
dependabot[bot] 35ef9b3c8b
build(deps): bump cc from 1.2.26 to 1.2.27 (#3969)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.26 to 1.2.27.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.26...cc-v1.2.27)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.27
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-16 12:26:07 -04:00
dependabot[bot] 4922138b3e
build(deps): bump prettyplease from 0.2.33 to 0.2.34 (#3967)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.33 to 0.2.34.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.33...0.2.34)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-version: 0.2.34
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-16 12:22:48 -04:00
dependabot[bot] 47f3817dea
build(deps): bump memchr from 2.7.4 to 2.7.5 (#3966)
Bumps [memchr](https://github.com/BurntSushi/memchr) from 2.7.4 to 2.7.5.
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.4...2.7.5)

---
updated-dependencies:
- dependency-name: memchr
  dependency-version: 2.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-12 16:04:26 -04:00
dependabot[bot] 15bcb9a056
build(deps): bump cfg-if from 1.0.0 to 1.0.1 (#3965)
Bumps [cfg-if](https://github.com/rust-lang/cfg-if) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/rust-lang/cfg-if/releases)
- [Changelog](https://github.com/rust-lang/cfg-if/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cfg-if/compare/1.0.0...v1.0.1)

---
updated-dependencies:
- dependency-name: cfg-if
  dependency-version: 1.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-12 16:03:01 -04:00
dependabot[bot] 25212a4423
build(deps): bump softprops/action-gh-release from 2.3.0 to 2.3.2 (#3964)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.3.0 to 2.3.2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](d5382d3e6f...72f2c25fcb)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 2.3.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-12 08:45:20 -07:00
dependabot[bot] 4cd1fbf69a
build(deps): bump wasi (#3963)
Bumps [wasi](https://github.com/bytecodealliance/wasi) from 0.11.0+wasi-snapshot-preview1 to 0.11.1+wasi-snapshot-preview1.
- [Commits](https://github.com/bytecodealliance/wasi/compare/0.11.0...0.11.1)

---
updated-dependencies:
- dependency-name: wasi
  dependency-version: 0.11.1+wasi-snapshot-preview1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-11 11:30:55 -04:00
dependabot[bot] f2c68aa010
build(deps): bump smallvec from 1.15.0 to 1.15.1 (#3962)
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.15.0 to 1.15.1.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.15.0...v1.15.1)

---
updated-dependencies:
- dependency-name: smallvec
  dependency-version: 1.15.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-11 11:30:31 -04:00
dependabot[bot] 14c3716fcd
build(deps): bump miniz_oxide from 0.8.8 to 0.8.9 (#3961)
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.8.8 to 0.8.9.
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/commits)

---
updated-dependencies:
- dependency-name: miniz_oxide
  dependency-version: 0.8.9
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-11 11:30:20 -04:00
dependabot[bot] 6118756991
build(deps): bump adler2 from 2.0.0 to 2.0.1 (#3960)
Bumps [adler2](https://github.com/oyvindln/adler2) from 2.0.0 to 2.0.1.
- [Changelog](https://github.com/oyvindln/adler2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/oyvindln/adler2/commits)

---
updated-dependencies:
- dependency-name: adler2
  dependency-version: 2.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-10 10:11:16 -04:00
dependabot[bot] f508e7998c
build(deps): bump syn from 2.0.101 to 2.0.102 (#3959)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.101 to 2.0.102.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.101...2.0.102)

---
updated-dependencies:
- dependency-name: syn
  dependency-version: 2.0.102
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-10 10:10:40 -04:00
dependabot[bot] 9ed7f8cf7d
build(deps): bump rustc-demangle from 0.1.24 to 0.1.25 (#3958)
Bumps [rustc-demangle](https://github.com/rust-lang/rustc-demangle) from 0.1.24 to 0.1.25.
- [Commits](https://github.com/rust-lang/rustc-demangle/commits)

---
updated-dependencies:
- dependency-name: rustc-demangle
  dependency-version: 0.1.25
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-10 10:10:15 -04:00
dependabot[bot] 3da6013871
build(deps): bump softprops/action-gh-release from 2.2.2 to 2.3.0 (#3957)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.2.2 to 2.3.0.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](da05d55257...d5382d3e6f)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-10 10:09:51 -04:00
dependabot[bot] 66d558b8b2
build(deps): bump cc from 1.2.25 to 1.2.26 (#3956)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.25 to 1.2.26.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.25...cc-v1.2.26)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.26
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 11:35:37 -04:00
dependabot[bot] ede8a97d25
build(deps): bump tracing-attributes in the tracing group (#3955)
Bumps the tracing group with 1 update: [tracing-attributes](https://github.com/tokio-rs/tracing).


Updates `tracing-attributes` from 0.1.28 to 0.1.29
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-attributes-0.1.28...tracing-attributes-0.1.29)

---
updated-dependencies:
- dependency-name: tracing-attributes
  dependency-version: 0.1.29
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: tracing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 11:35:23 -04:00
dependabot[bot] 44cfdfd7fe
build(deps): bump flate2 from 1.1.1 to 1.1.2 (#3954)
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.1...1.1.2)

---
updated-dependencies:
- dependency-name: flate2
  dependency-version: 1.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 11:35:07 -04:00
dependabot[bot] 8a515a3cc0
build(deps): bump portable-atomic from 1.11.0 to 1.11.1 (#3952)
Bumps [portable-atomic](https://github.com/taiki-e/portable-atomic) from 1.11.0 to 1.11.1.
- [Release notes](https://github.com/taiki-e/portable-atomic/releases)
- [Changelog](https://github.com/taiki-e/portable-atomic/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/portable-atomic/compare/v1.11.0...v1.11.1)

---
updated-dependencies:
- dependency-name: portable-atomic
  dependency-version: 1.11.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-06 10:53:05 -04:00
dependabot[bot] d1ecb03c9f
build(deps): bump bumpalo from 3.17.0 to 3.18.1 (#3951)
Bumps [bumpalo](https://github.com/fitzgen/bumpalo) from 3.17.0 to 3.18.1.
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.17.0...v3.18.1)

---
updated-dependencies:
- dependency-name: bumpalo
  dependency-version: 3.18.1
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-06 10:52:47 -04:00
dependabot[bot] f4ae038d79
build(deps): bump tracing-core in the tracing group (#3950)
Bumps the tracing group with 1 update: [tracing-core](https://github.com/tokio-rs/tracing).


Updates `tracing-core` from 0.1.33 to 0.1.34
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-core-0.1.33...tracing-core-0.1.34)

---
updated-dependencies:
- dependency-name: tracing-core
  dependency-version: 0.1.34
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: tracing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-06 10:52:38 -04:00
dependabot[bot] 3aa53596f7
build(deps): bump hyper-util from 0.1.13 to 0.1.14 (#3948)
Bumps [hyper-util](https://github.com/hyperium/hyper-util) from 0.1.13 to 0.1.14.
- [Release notes](https://github.com/hyperium/hyper-util/releases)
- [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.13...v0.1.14)

---
updated-dependencies:
- dependency-name: hyper-util
  dependency-version: 0.1.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-05 06:51:50 -07:00
katelyn martin 67dc85a367
chore(app/test): remove unused dependencies (#3932)
`linkerd-app-test` relies on some dependencies that are unused.

this commit removes these dependencies from the crate's manifest.

see #3928 and #3929.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-06-02 15:10:53 -07:00
katelyn martin ea6f407c57
fix(http/retry): `PeekTrailersBody<B>` retains first frame (#3947)
see linkerd/linkerd2#14050.

this change fixes a logical bug with
`linkerd_http_retry::peek_trailers::PeekTrailersBody::<B>::read_body(..)`.

`read_body(..)` constructs a `PeekTrailersBody<B>`, by polling the inner
body to see whether or not it can reach the end of the stream by only
yielding to the asynchronous runtime once.

in linkerd/linkerd2-proxy#3559, we restructured this middleware's
internal modeling to reflect the `Frame<T>`-oriented signatures of the
`http_body::Body` trait's 1.0 interface.

unfortunately, this included a bug which could cause the first frame in
a stream to be discarded if the second `Body::poll_frame()` call
(_invoked via `now_or_never()`_) returns `Pending`. this could cause
non-deterministic errors for users when sending traffic to HTTPRoutes
and GRPCRoutes with retry annotations applied.

this change rectifies this problem, ensuring that the first frame is not
discarded when attempting to peek a body's trailers.

to confirm that this works as expected, additional test coverage is
introduced that confirms that the data and trailers of the inner body
are passed through faithfully.

---

* feat(http/retry): additional `PeekTrailersBody<B>` test coverage

this commit introduces additional test coverage to
`linker_http_retry::peek_trailers::PeekTrailersBody<B>`.

this body middleware is used to facilitate transparent http retries, and
allows callers to possibly inspect the trailers for a response, by
polling an `http_body::Body`.

this commit introduces additional unit test coverage that confirms that
the data and trailers of the inner body are passed through faithfully.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): another `PeekTrailersBody<B>` test case

this commit introduces some additional coverage for bodies that return
`Pending` when polled a second time.

Signed-off-by: katelyn martin <kate@buoyant.io>

* fix(http/retry): `PeekTrailersBody<B>` retains first frame

this commit fixes a logical bug with
`linkerd_http_retry::peek_trailers::PeekTrailersBody::<B>::read_body(..)`.

`read_body(..)` constructs a `PeekTrailersBody<B>`, by polling the inner
body to see whether or not it can reach the end of the stream by only
yielding to the asynchronous runtime once.

in linkerd/linkerd2-proxy#3559, we restructured this middleware's
internal modeling to reflect the `Frame<T>`-oriented signatures of the
`http_body::Body` trait's 1.0 interface.

unfortunately, this included a bug which could cause the first frame in
a stream to be discarded if the second `Body::poll_frame()` call
(_invoked via `now_or_never()`_) returns `Pending`. this could cause
non-deterministic errors for users when sending traffic to HTTPRoutes
and GRPCRoutes with retry annotations applied.

this commit rectifies this problem, ensuring that the first frame is not
discarded when attempting to peek a body's trailers.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-06-02 09:53:24 -07:00
dependabot[bot] c36bef6b47
build(deps): bump num_cpus from 1.16.0 to 1.17.0 (#3946)
Bumps [num_cpus](https://github.com/seanmonstar/num_cpus) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/seanmonstar/num_cpus/releases)
- [Changelog](https://github.com/seanmonstar/num_cpus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/num_cpus/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: num_cpus
  dependency-version: 1.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 08:51:23 -04:00
dependabot[bot] 12822d1848
build(deps): bump cc from 1.2.24 to 1.2.25 (#3945)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.24 to 1.2.25.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.24...cc-v1.2.25)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.25
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 08:51:10 -04:00
dependabot[bot] 66b5f330c3
build(deps): bump prettyplease from 0.2.32 to 0.2.33 (#3944)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.32 to 0.2.33.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.32...0.2.33)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-version: 0.2.33
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 08:50:58 -04:00
dependabot[bot] 423b5c07e6
build(deps): bump parking_lot from 0.12.3 to 0.12.4 (#3943)
Bumps [parking_lot](https://github.com/Amanieu/parking_lot) from 0.12.3 to 0.12.4.
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/0.12.3...parking_lot-v0.12.4)

---
updated-dependencies:
- dependency-name: parking_lot
  dependency-version: 0.12.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-30 08:18:04 -04:00
dependabot[bot] 0a17238d10
build(deps): bump parking_lot_core from 0.9.10 to 0.9.11 (#3942)
Bumps [parking_lot_core](https://github.com/Amanieu/parking_lot) from 0.9.10 to 0.9.11.
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/core-0.9.10...parking_lot_core-v0.9.11)

---
updated-dependencies:
- dependency-name: parking_lot_core
  dependency-version: 0.9.11
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-30 08:17:37 -04:00
dependabot[bot] cbfef553ce
build(deps): bump lock_api from 0.4.12 to 0.4.13 (#3941)
Bumps [lock_api](https://github.com/Amanieu/parking_lot) from 0.4.12 to 0.4.13.
- [Release notes](https://github.com/Amanieu/parking_lot/releases)
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-0.4.12...lock_api-v0.4.13)

---
updated-dependencies:
- dependency-name: lock_api
  dependency-version: 0.4.13
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-30 08:17:20 -04:00
dependabot[bot] 6233b47dd3
build(deps): bump libloading from 0.8.7 to 0.8.8 (#3940)
Bumps [libloading](https://github.com/nagisa/rust_libloading) from 0.8.7 to 0.8.8.
- [Commits](https://github.com/nagisa/rust_libloading/commits)

---
updated-dependencies:
- dependency-name: libloading
  dependency-version: 0.8.8
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-29 10:44:53 -04:00
dependabot[bot] 19bfb14f1f
build(deps): bump pprof from 0.14.0 to 0.15.0 (#3938)
Bumps [pprof](https://github.com/tikv/pprof-rs) from 0.14.0 to 0.15.0.
- [Changelog](https://github.com/tikv/pprof-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tikv/pprof-rs/commits)

---
updated-dependencies:
- dependency-name: pprof
  dependency-version: 0.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 11:13:34 -04:00
dependabot[bot] c6eea70f1a
build(deps): bump hyper-util from 0.1.12 to 0.1.13 (#3939)
Bumps [hyper-util](https://github.com/hyperium/hyper-util) from 0.1.12 to 0.1.13.
- [Release notes](https://github.com/hyperium/hyper-util/releases)
- [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.12...v0.1.13)

---
updated-dependencies:
- dependency-name: hyper-util
  dependency-version: 0.1.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 11:13:08 -04:00
dependabot[bot] 96d7c25704
build(deps): bump the boring group with 3 updates (#3937)
Bumps the boring group with 3 updates: [boring](https://github.com/cloudflare/boring), [tokio-boring](https://github.com/cloudflare/boring) and [boring-sys](https://github.com/cloudflare/boring).


Updates `boring` from 4.16.0 to 4.17.0
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.16.0...v4.17.0)

Updates `tokio-boring` from 4.16.0 to 4.17.0
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.16.0...v4.17.0)

Updates `boring-sys` from 4.16.0 to 4.17.0
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.16.0...v4.17.0)

---
updated-dependencies:
- dependency-name: boring
  dependency-version: 4.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: boring
- dependency-name: tokio-boring
  dependency-version: 4.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: boring
- dependency-name: boring-sys
  dependency-version: 4.17.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: boring
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 08:23:55 -04:00
dependabot[bot] 1450af00d8
build(deps): bump the opentelemetry group with 2 updates (#3934)
Bumps the opentelemetry group with 2 updates: [opentelemetry](https://github.com/open-telemetry/opentelemetry-rust) and [opentelemetry_sdk](https://github.com/open-telemetry/opentelemetry-rust).


Updates `opentelemetry` from 0.29.1 to 0.30.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-rust/releases)
- [Commits](https://github.com/open-telemetry/opentelemetry-rust/compare/opentelemetry-0.29.1...opentelemetry-0.30.0)

Updates `opentelemetry_sdk` from 0.29.0 to 0.30.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-rust/releases)
- [Commits](https://github.com/open-telemetry/opentelemetry-rust/compare/opentelemetry_sdk-0.29.0...opentelemetry_sdk-0.30.0)

---
updated-dependencies:
- dependency-name: opentelemetry
  dependency-version: 0.30.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry
- dependency-name: opentelemetry_sdk
  dependency-version: 0.30.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 07:17:39 -07:00
dependabot[bot] 27f62ad034
build(deps): bump mio from 1.0.3 to 1.0.4 (#3933)
Bumps [mio](https://github.com/tokio-rs/mio) from 1.0.3 to 1.0.4.
- [Release notes](https://github.com/tokio-rs/mio/releases)
- [Changelog](https://github.com/tokio-rs/mio/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/mio/commits)

---
updated-dependencies:
- dependency-name: mio
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 09:35:24 -04:00
dependabot[bot] fefa7c0cbf
build(deps): bump socket2 from 0.5.9 to 0.5.10 (#3936)
Bumps [socket2](https://github.com/rust-lang/socket2) from 0.5.9 to 0.5.10.
- [Release notes](https://github.com/rust-lang/socket2/releases)
- [Changelog](https://github.com/rust-lang/socket2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/socket2/commits)

---
updated-dependencies:
- dependency-name: socket2
  dependency-version: 0.5.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 09:33:06 -04:00
katelyn martin b3549bc767
chore(app/test): remove unused functions (#3929)
`linkerd-app-test` exposes some functions that we never use elsewhere.

this commit removes these functions.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-23 09:25:12 -07:00
katelyn martin c00ce3241b
chore(app/test): remove unused `service` submodule (#3928)
`linkerd_app_test::service` contains facilities that are unused.

this commit removes this submodule from the `linkerd-app-test` library.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-23 09:25:00 -07:00
dependabot[bot] 21fd4ec51b
build(deps): bump rustversion from 1.0.20 to 1.0.21 (#3931)
Bumps [rustversion](https://github.com/dtolnay/rustversion) from 1.0.20 to 1.0.21.
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.20...1.0.21)

---
updated-dependencies:
- dependency-name: rustversion
  dependency-version: 1.0.21
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 08:38:35 -04:00
dependabot[bot] fa0c104931
build(deps): bump cc from 1.2.23 to 1.2.24 (#3930)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.23 to 1.2.24.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.23...cc-v1.2.24)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.24
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 08:38:10 -04:00
katelyn martin cab7adc456
chore(meshtls/boring): sort dependencies (#3927)
Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-22 16:20:58 -04:00
katelyn martin 478e1e151f
chore(deps): bump DavidAnson/markdownlint-cli2-action (#3923)
* chore(docs): address `no-generic-link-test` lint (#3923)

this addresses errors observed by dependabot when upgrading to the
latest version of `markdownlint`.

there is a new lint, added in DavidAnson/markdownlint#1459, that
introduces forbidden link text to discourage generic `here` text in
links.

this fixes sentences that included a link labeled "here".

* https://github.com/linkerd/linkerd2-proxy/pull/3918
* https://github.com/linkerd/linkerd2-proxy/actions/runs/15043224730/job/42279610780?pr=3918
* https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md059.md
* https://github.com/DavidAnson/markdownlint/pull/1459
* https://github.com/DavidAnson/markdownlint/issues/681

```
 Summary: 3 error(s)
Error: docs/FUZZING.md:17:13 MD059/descriptive-link-text Link text should be descriptive [Context: "[here]"] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md059.md
Error: docs/FUZZING.md💯2 MD059/descriptive-link-text Link text should be descriptive [Context: "[here]"] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md059.md
Error: README.md:90:2 MD059/descriptive-link-text Link text should be descriptive [Context: "[here]"] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md059.md
Error: Failed with exit code: 1
```

Signed-off-by: katelyn martin <kate@buoyant.io>

* build(deps): bump DavidAnson/markdownlint-cli2-action (#3923)

Bumps [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action) from 19.1.0 to 20.0.0.
- [Release notes](https://github.com/davidanson/markdownlint-cli2-action/releases)
- [Commits](05f32210e8...992badcdf2)

---
updated-dependencies:
- dependency-name: DavidAnson/markdownlint-cli2-action
  dependency-version: 20.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 13:16:37 -07:00
dependabot[bot] 1eeae37018
build(deps): bump jiff from 0.2.13 to 0.2.14 (#3926)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.13 to 0.2.14.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.13...jiff-static-0.2.14)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-21 10:29:08 -04:00
dependabot[bot] 83d4eacb27
build(deps): bump hyper-util from 0.1.11 to 0.1.12 (#3925)
Bumps [hyper-util](https://github.com/hyperium/hyper-util) from 0.1.11 to 0.1.12.
- [Release notes](https://github.com/hyperium/hyper-util/releases)
- [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.11...v0.1.12)

---
updated-dependencies:
- dependency-name: hyper-util
  dependency-version: 0.1.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-20 09:15:20 -04:00
dependabot[bot] ddc590f38b
build(deps): bump the icu4x group with 2 updates (#3924)
Bumps the icu4x group with 2 updates: [icu_properties](https://github.com/unicode-org/icu4x) and [icu_properties_data](https://github.com/unicode-org/icu4x).


Updates `icu_properties` from 2.0.0 to 2.0.1
- [Release notes](https://github.com/unicode-org/icu4x/releases)
- [Changelog](https://github.com/unicode-org/icu4x/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unicode-org/icu4x/commits)

Updates `icu_properties_data` from 2.0.0 to 2.0.1
- [Release notes](https://github.com/unicode-org/icu4x/releases)
- [Changelog](https://github.com/unicode-org/icu4x/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unicode-org/icu4x/commits)

---
updated-dependencies:
- dependency-name: icu_properties
  dependency-version: 2.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: icu4x
- dependency-name: icu_properties_data
  dependency-version: 2.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: icu4x
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-20 09:14:43 -04:00
dependabot[bot] 0f42f15102
build(deps): bump codecov/codecov-action from 5.4.2 to 5.4.3 (#3920)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.2 to 5.4.3.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](ad3126e916...18283e04ce)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 5.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-16 16:21:34 -04:00
dependabot[bot] 20f47ad9de
build(deps): bump errno from 0.3.11 to 0.3.12 (#3922)
Bumps [errno](https://github.com/lambda-fairy/rust-errno) from 0.3.11 to 0.3.12.
- [Release notes](https://github.com/lambda-fairy/rust-errno/releases)
- [Changelog](https://github.com/lambda-fairy/rust-errno/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lambda-fairy/rust-errno/compare/v0.3.11...v0.3.12)

---
updated-dependencies:
- dependency-name: errno
  dependency-version: 0.3.12
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-16 10:01:34 -04:00
dependabot[bot] 7abe88119c
build(deps): bump cc from 1.2.22 to 1.2.23 (#3921)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.22 to 1.2.23.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.22...cc-v1.2.23)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.23
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-16 10:01:02 -04:00
katelyn martin 37c0f96cfc
nit(app): consolidate `impl Config` blocks (#3919)
this is a trivial, cosmetic change.

`Config` has two consecutive `impl` blocks in the `linkerd-app` library.
these do not include distinct generics or trait bounds, so the methods
contained therein do not need to live in two distinct `impl` blocks.

this commit consolidates these blocks.

while we are performing this change, we add two `=== impl T ===`
banners, which are used throughout the project as greppable strings to
find methods and trait implementations for a given type.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-16 09:37:02 -04:00
dependabot[bot] 79e10775f0
build(deps): bump generator from 0.8.4 to 0.8.5 (#3917)
Bumps [generator](https://github.com/Xudong-Huang/generator-rs) from 0.8.4 to 0.8.5.
- [Release notes](https://github.com/Xudong-Huang/generator-rs/releases)
- [Commits](https://github.com/Xudong-Huang/generator-rs/compare/0.8.4...0.8.5)

---
updated-dependencies:
- dependency-name: generator
  dependency-version: 0.8.5
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-14 09:29:51 -04:00
dependabot[bot] a2eadec54a
build(deps): bump resolv-conf from 0.7.3 to 0.7.4 (#3916)
Bumps [resolv-conf](https://github.com/hickory-dns/resolv-conf) from 0.7.3 to 0.7.4.
- [Release notes](https://github.com/hickory-dns/resolv-conf/releases)
- [Commits](https://github.com/hickory-dns/resolv-conf/compare/v0.7.3...v0.7.4)

---
updated-dependencies:
- dependency-name: resolv-conf
  dependency-version: 0.7.4
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-13 09:53:37 -04:00
katelyn martin 7b7ffbc69d
chore(deps): define `tracing` workspace dependency (#3834)
this commit hoists `tracing`, used liberally throughout our project,
such that it is managed as a single workspace dependency.

this will be helpful someday when a 0.2 release happens.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-12 16:00:34 -04:00
katelyn martin 00b5de1936
refactor(proxy/http): a concrete `orig_proto` error (#3901)
this commit introduces a concrete error type for the `orig_proto`
upgrade layer.

this layer is used by the proxy's http client to transparently upgrade
outbound http/1 traffic to http/2. rather than boxing errors, we define
a concrete error type to facilitate inspecting errors in the future.

for now, the top-level http client continues to box errors thrown by the
"orig_proto" upgrade client.

see also, #3894 (ea75ac0).

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-12 15:59:56 -04:00
katelyn martin d3a176446c
fix: report error causes properly (#3915)
the `linkerd-error` crate includes two functions that can be used to
examine the cause of a dynamic, boxed error. for example, here is the
`is_caused_by()` function, used in some of our error recovery logic:

```rust
/// Determines whether the provided error was caused by an `E` typed error.
pub fn is_caused_by<E: std::error::Error + 'static>(
    mut error: &(dyn std::error::Error + 'static),
) -> bool {
    loop {
        if error.is::<E>() {
            return true;
        }
        error = match error.source() {
            Some(e) => e,
            None => return false,
        };
    }
}
```

we rely on [`thiserror`](https://github.com/dtolnay/thiserror/) to
generate boilerplate code for our error structures. this includes an
attribute called `transparent` that will delegate down to an inner
error.

however, this delegation means that the causal chains inspected by
the function above might not properly identify an inner error. this
test, for example, fails:

```rust
// linkerd/dns/src/lib.rs
#[derive(Debug, Clone, Error)]
#[error("invalid SRV record {:?}", self.0)]
struct InvalidSrv(rdata::SRV);

#[derive(Debug, Error)]
enum SrvRecordError {
    #[error(transparent)]
    Invalid(#[from] InvalidSrv),
    #[error("failed to resolve SRV record: {0}")]
    Resolve(#[from] hickory_resolver::ResolveError),
}

#[test]
fn srv_record_reports_cause_correctly() {
    let srv = "foobar.linkerd-dst-headless.linkerd.svc.cluster.local."
        .parse::<hickory_resolver::Name>()
        .map(|name| rdata::SRV::new(1, 1, 8086, name))
        .expect("a valid domain name");

    let error = SrvRecordError::Invalid(InvalidSrv(srv));
    let error: Box<dyn std::error::Error + 'static> = Box::new(error);

    assert!(linkerd_error::is_caused_by::<InvalidSrv>(&*error));
    assert!(linkerd_error::cause_ref::<InvalidSrv>(&*error).is_some());
}
```

the `transparent` attribute will delegate directly down to `InvalidSrv`
when `Error::source()` is invoked. this means that our downcasting logic
in `linkerd-error` used to ascertain causes of dynamic, boxed errors
will fail to identify a `SrvRecordError` as being caused by an
`InvalidSrv`.

by replacing the `transparent` attribute with a `"{0}"` display
attribute, we continue to transparently show the inner error when
printed as a string, but will include `InvalidSrv` in the causal chain.

this branch replaces `transparent` attributes in an assortment of
error variants.

---

* test(dns): add a failing test

this commit adds a failing unit test. this test shows that dns errors
might not report their cause correctly, due to thiserror's `transparent`
attribute passing directly through to `InvalidSrv`'s cause.

Signed-off-by: katelyn martin <kate@buoyant.io>

* fix(dns): replace `error(transparent)` attribute

this commit fixes the failing unit test introduced in the previous
commit.

the `transparent` attribute will delegate directly down to `InvalidSrv`
when `Error::source()` is invoke. this means that our downcasting logic
in `linkerd-error` used to ascertain causes of dynamic, boxed errors
will fail to identify a `SrvRecordError` as being caused by an
`InvalidSrv`.

by replacing the `transparent` attribute with a `"{0}"` display
attribute, we continue to transparently show the inner error when
printed as a string, but will include `InvalidSrv` in the causal chain.

Signed-off-by: katelyn martin <kate@buoyant.io>

* fix: errors report inner sources

this commit performs the same transformation as the previous commit,
replacing `transparent` with equivalent pass-through `"{0}"` display
strings, adding `#[source]` where needed.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-12 15:52:06 -04:00
katelyn martin 015c499891
refactor(app/outbound): `Connect` fields are not pub (#3895)
this structure exposes its fields, but those fields are never accessed
elsewhere, aside from test code.

this commit removes the `pub` directives from the address and tls
fields. in their stead, test interfaces are added to allow the
`tagged_transport` test suite to function.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-12 15:38:59 -04:00
katelyn martin ea75ac0126
refactor(proxy/http): http/1 client is a `Service<T>` (#3894)
this is a small mechanical refactor to the http/1 client.

our http/2 and "orig_proto" clients are tower services. our http/1
client, on the other hand, exposes a concrete inherent method `request`.

to be consistent, this changes our http client to treat this http/1
client as a service as well.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-12 15:38:26 -04:00
katelyn martin 3a795967af
nit(app/integration): sort cargo dependencies (#3887)
this alphabetizes dependencies in `linkerd-app-integration`'s
manifest.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-05-12 15:37:52 -04:00
dependabot[bot] c5c2c24b0d
build(deps): bump libloading from 0.8.6 to 0.8.7 (#3914)
Bumps [libloading](https://github.com/nagisa/rust_libloading) from 0.8.6 to 0.8.7.
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.6...0.8.7)

---
updated-dependencies:
- dependency-name: libloading
  dependency-version: 0.8.7
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 10:00:18 -04:00
dependabot[bot] 971ec0e14d
build(deps): bump multimap from 0.10.0 to 0.10.1 (#3913)
Bumps [multimap](https://github.com/havarnov/multimap) from 0.10.0 to 0.10.1.
- [Commits](https://github.com/havarnov/multimap/commits)

---
updated-dependencies:
- dependency-name: multimap
  dependency-version: 0.10.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 10:00:01 -04:00
dependabot[bot] f45a6185f6
build(deps): bump tempfile from 3.19.1 to 3.20.0 (#3912)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.19.1 to 3.20.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.19.1...v3.20.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-version: 3.20.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 09:58:57 -04:00
dependabot[bot] 6ea7f158a5
build(deps): bump aws-lc-rs from 1.13.0 to 1.13.1 (#3911)
Bumps [aws-lc-rs](https://github.com/aws/aws-lc-rs) from 1.13.0 to 1.13.1.
- [Release notes](https://github.com/aws/aws-lc-rs/releases)
- [Commits](https://github.com/aws/aws-lc-rs/compare/v1.13.0...v1.13.1)

---
updated-dependencies:
- dependency-name: aws-lc-rs
  dependency-version: 1.13.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 13:12:34 -04:00
dependabot[bot] 0e9f9443b8
build(deps): bump cc from 1.2.21 to 1.2.22 (#3910)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.21 to 1.2.22.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.21...cc-v1.2.22)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.22
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 13:12:23 -04:00
dependabot[bot] 34dae165d6
build(deps): bump idna_adapter from 1.2.0 to 1.2.1 (#3909)
Bumps [idna_adapter](https://github.com/hsivonen/idna_adapter) from 1.2.0 to 1.2.1.
- [Commits](https://github.com/hsivonen/idna_adapter/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: idna_adapter
  dependency-version: 1.2.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 13:12:15 -04:00
dependabot[bot] 9063a6df66
build(deps): bump backtrace from 0.3.74 to 0.3.75 (#3907)
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.74 to 0.3.75.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.74...0.3.75)

---
updated-dependencies:
- dependency-name: backtrace
  dependency-version: 0.3.75
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 10:21:51 -04:00
dependabot[bot] a9ce356bf8
build(deps): bump jiff from 0.2.12 to 0.2.13 (#3906)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.12 to 0.2.13.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.12...jiff-static-0.2.13)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-06 11:11:16 -04:00
dependabot[bot] dd432b3143
build(deps): bump tokio from 1.44.2 to 1.45.0 (#3905)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.44.2 to 1.45.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.44.2...tokio-1.45.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.45.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-06 10:52:23 -04:00
dependabot[bot] d35e12facb
build(deps): bump jiff from 0.2.11 to 0.2.12 (#3900)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.11 to 0.2.12.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.11...jiff-static-0.2.12)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 09:19:42 -04:00
dependabot[bot] 430eb75667
build(deps): bump the hickory group with 2 updates (#3899)
Bumps the hickory group with 2 updates: [hickory-resolver](https://github.com/hickory-dns/hickory-dns) and [hickory-proto](https://github.com/hickory-dns/hickory-dns).


Updates `hickory-resolver` from 0.25.1 to 0.25.2
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/main/OLD-CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.25.1...v0.25.2)

Updates `hickory-proto` from 0.25.1 to 0.25.2
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/main/OLD-CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.25.1...v0.25.2)

---
updated-dependencies:
- dependency-name: hickory-resolver
  dependency-version: 0.25.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: hickory
- dependency-name: hickory-proto
  dependency-version: 0.25.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: hickory
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 09:18:40 -04:00
dependabot[bot] 025f0a19cb
build(deps): bump the symbolic group with 2 updates (#3896)
Bumps the symbolic group with 2 updates: [symbolic-common](https://github.com/getsentry/symbolic) and [symbolic-demangle](https://github.com/getsentry/symbolic).


Updates `symbolic-common` from 12.15.4 to 12.15.5
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.15.4...12.15.5)

Updates `symbolic-demangle` from 12.15.4 to 12.15.5
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.15.4...12.15.5)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-version: 12.15.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: symbolic
- dependency-name: symbolic-demangle
  dependency-version: 12.15.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: symbolic
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 11:00:55 -04:00
dependabot[bot] d9ed5e3835
build(deps): bump jiff from 0.2.10 to 0.2.11 (#3898)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.10 to 0.2.11.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.10...jiff-static-0.2.11)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 11:00:28 -04:00
dependabot[bot] f2e4961a4b
build(deps): bump cc from 1.2.20 to 1.2.21 (#3897)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.20 to 1.2.21.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.20...cc-v1.2.21)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.21
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 10:59:54 -04:00
dependabot[bot] facaf571d8
build(deps): bump sha2 from 0.10.8 to 0.10.9 (#3893)
Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.10.8 to 0.10.9.
- [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.8...sha2-v0.10.9)

---
updated-dependencies:
- dependency-name: sha2
  dependency-version: 0.10.9
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 10:55:25 -04:00
dependabot[bot] 905f71fa25
build(deps): bump resolv-conf from 0.7.1 to 0.7.3 (#3892)
Bumps [resolv-conf](https://github.com/hickory-dns/resolv-conf) from 0.7.1 to 0.7.3.
- [Release notes](https://github.com/hickory-dns/resolv-conf/releases)
- [Commits](https://github.com/hickory-dns/resolv-conf/compare/v0.7.1...v0.7.3)

---
updated-dependencies:
- dependency-name: resolv-conf
  dependency-version: 0.7.3
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 10:55:14 -04:00
dependabot[bot] c822b72786
build(deps): bump synstructure from 0.13.1 to 0.13.2 (#3891)
Bumps [synstructure](https://github.com/mystor/synstructure) from 0.13.1 to 0.13.2.
- [Commits](https://github.com/mystor/synstructure/commits)

---
updated-dependencies:
- dependency-name: synstructure
  dependency-version: 0.13.2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 10:54:55 -04:00
dependabot[bot] b6a07aa01e
build(deps): bump tokio-metrics from 0.4.1 to 0.4.2 (#3890)
Bumps [tokio-metrics](https://github.com/tokio-rs/tokio-metrics) from 0.4.1 to 0.4.2.
- [Release notes](https://github.com/tokio-rs/tokio-metrics/releases)
- [Changelog](https://github.com/tokio-rs/tokio-metrics/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/tokio-metrics/compare/v0.4.1...v0.4.2)

---
updated-dependencies:
- dependency-name: tokio-metrics
  dependency-version: 0.4.2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 10:54:44 -04:00
dependabot[bot] f657ceabb4
build(deps): bump aws-lc-fips-sys from 0.13.5 to 0.13.6 (#3889)
Bumps [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) from 0.13.5 to 0.13.6.
- [Release notes](https://github.com/aws/aws-lc-rs/releases)
- [Commits](https://github.com/aws/aws-lc-rs/compare/aws-lc-fips-sys/v0.13.5...aws-lc-fips-sys/v0.13.6)

---
updated-dependencies:
- dependency-name: aws-lc-fips-sys
  dependency-version: 0.13.6
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-29 09:12:22 -04:00
dependabot[bot] 89e28324da
build(deps): bump syn from 2.0.100 to 2.0.101 (#3886)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.100 to 2.0.101.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.100...2.0.101)

---
updated-dependencies:
- dependency-name: syn
  dependency-version: 2.0.101
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-28 09:40:18 -04:00
Scott Fleener 577a67b2c6
feat(meshtls): Add aws-lc-rs as optional rustls backend (#3883)
This has a few benefits. Primarily this gives us a reasonable path to creating FIPS-enabled builds on architectures other than x86-64, as well as a path away from using BoringSSL as a backend.

Additionally, rustls has been using the aws-lc-rs library as the default backend for a little while now, so this gives us the opportunity to stay in line with the most widely used option in the ecosystem.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-04-28 08:38:40 -04:00
dependabot[bot] b4fb4277d4
build(deps): bump actions/download-artifact from 4.2.1 to 4.3.0 (#3885)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.2.1 to 4.3.0.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](95815c38cf...d3f86a106a)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-25 10:28:33 -04:00
dependabot[bot] 5e626ef240
build(deps): bump cc from 1.2.19 to 1.2.20 (#3884)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.19 to 1.2.20.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.19...cc-v1.2.20)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.20
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-25 09:35:30 -04:00
dependabot[bot] d4c8a74596
build(deps): bump tokio-util from 0.7.14 to 0.7.15 (#3882)
Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.14 to 0.7.15.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.14...tokio-util-0.7.15)

---
updated-dependencies:
- dependency-name: tokio-util
  dependency-version: 0.7.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-24 13:22:17 -04:00
dependabot[bot] ff162dba22
build(deps): bump getrandom from 0.2.15 to 0.2.16 (#3881)
Bumps [getrandom](https://github.com/rust-random/getrandom) from 0.2.15 to 0.2.16.
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.2.15...v0.2.16)

---
updated-dependencies:
- dependency-name: getrandom
  dependency-version: 0.2.16
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-23 10:53:37 -04:00
dependabot[bot] 266ec108ac
build(deps): bump the symbolic group with 2 updates (#3880)
Bumps the symbolic group with 2 updates: [symbolic-common](https://github.com/getsentry/symbolic) and [symbolic-demangle](https://github.com/getsentry/symbolic).


Updates `symbolic-common` from 12.15.3 to 12.15.4
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.15.3...12.15.4)

Updates `symbolic-demangle` from 12.15.3 to 12.15.4
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.15.3...12.15.4)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-version: 12.15.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: symbolic
- dependency-name: symbolic-demangle
  dependency-version: 12.15.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: symbolic
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-23 10:53:25 -04:00
dependabot[bot] c4ded832b8
build(deps): bump jiff from 0.2.9 to 0.2.10 (#3879)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.9 to 0.2.10.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.9...jiff-static-0.2.10)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-22 10:44:42 -04:00
dependabot[bot] dd38e6b45a
build(deps): bump tokio-metrics from 0.4.0 to 0.4.1 (#3878)
Bumps [tokio-metrics](https://github.com/tokio-rs/tokio-metrics) from 0.4.0 to 0.4.1.
- [Release notes](https://github.com/tokio-rs/tokio-metrics/releases)
- [Changelog](https://github.com/tokio-rs/tokio-metrics/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/tokio-metrics/compare/v0.4.0...v0.4.1)

---
updated-dependencies:
- dependency-name: tokio-metrics
  dependency-version: 0.4.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-22 10:43:19 -04:00
katelyn martin ad5952f021
nit(http/retry): remove extra body poll in tests (#3877)
the initial replay body, circa the usage of our "compatibility" layer
(4b53081, #3598), used to need an extra poll to confirm the absence of
trailers before it would report itself as reaching the end of the
stream. these tests were added in (afda8a7b3, #3583).

this was an artifact of how the compatibility middleware masked the
previous `poll_data()` and `poll_trailer()` methods behind a
forward-compatible `poll_frame()`- and `frame()`-oriented interface.

this commit removes these extra calls to `initial.frame().await`, now
that the initial body will report the end of stream without an extra
call to await a `None`.

X-ref: #3598
X-ref: #3583

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-04-21 09:54:12 -07:00
Oliver Gould d25bbf262a
chore(dev): introduce copilot instructions (#3873)
This introduces a GitHub Copilot instructions file under .github to guide AI-driven code generation and updates the devcontainer configuration accordingly.

The new instructions enforce Rust styling, error handling, and tracing conventions across the project. It ensures generated code passes `cargo fmt` and `clippy`, avoids unwraps, and uses structured logging.
2025-04-21 12:24:34 -04:00
Oliver Gould ce62199344
fix(client-policy): enable TLS hostnames via overrides (#3871)
In 65db3dd we enabled overriding the behavior to export TLS hostnames for
outbound traffic, but we omitted TLS hostname labels.

This change updates the tls module to mirror the http module's behavior.
2025-04-21 12:13:51 -04:00
dependabot[bot] 5ebea46ca2
build(deps): bump rand from 0.9.0 to 0.9.1 (#3872)
Bumps [rand](https://github.com/rust-random/rand) from 0.9.0 to 0.9.1.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.9.0...rand_core-0.9.1)

---
updated-dependencies:
- dependency-name: rand
  dependency-version: 0.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 07:59:03 -07:00
dependabot[bot] 0c343ce118
build(deps): bump jiff from 0.2.8 to 0.2.9 (#3876)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.8 to 0.2.9.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.8...jiff-static-0.2.9)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 09:24:57 -04:00
dependabot[bot] d3943c6833
build(deps): bump signal-hook-registry from 1.4.2 to 1.4.5 (#3875)
Bumps [signal-hook-registry](https://github.com/vorner/signal-hook) from 1.4.2 to 1.4.5.
- [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/signal-hook/compare/registry-v1.4.2...registry-v1.4.5)

---
updated-dependencies:
- dependency-name: signal-hook-registry
  dependency-version: 1.4.5
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 09:24:17 -04:00
dependabot[bot] 9135162dc8
build(deps): bump softprops/action-gh-release from 2.2.1 to 2.2.2 (#3874)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.2.1 to 2.2.2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](c95fe14893...da05d55257)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 2.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 09:23:36 -04:00
dependabot[bot] 2a34d40df4
build(deps): bump codecov/codecov-action from 5.4.0 to 5.4.2 (#3867)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.0 to 5.4.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](0565863a31...ad3126e916)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: 5.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 21:24:48 -07:00
dependabot[bot] ea1aa58255
build(deps): bump libc from 0.2.171 to 0.2.172 (#3868)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.171 to 0.2.172.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.172/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.171...0.2.172)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.172
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 21:24:26 -07:00
dependabot[bot] 46b90f8ae1
build(deps): bump proc-macro2 from 1.0.94 to 1.0.95 (#3869)
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.94 to 1.0.95.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.94...1.0.95)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-version: 1.0.95
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 21:24:12 -07:00
dependabot[bot] 13ab2f4825
build(deps): bump jiff from 0.2.6 to 0.2.8 (#3866)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.6 to 0.2.8.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.6...jiff-static-0.2.8)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-14 10:14:56 -04:00
dependabot[bot] dc3a31c156
build(deps): bump anyhow from 1.0.97 to 1.0.98 (#3865)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.97 to 1.0.98.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.97...1.0.98)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-version: 1.0.98
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-14 10:14:31 -04:00
dependabot[bot] c5e9098f3d
build(deps): bump data-encoding from 2.8.0 to 2.9.0 (#3864)
Bumps [data-encoding](https://github.com/ia0/data-encoding) from 2.8.0 to 2.9.0.
- [Commits](https://github.com/ia0/data-encoding/compare/v2.8.0...v2.9.0)

---
updated-dependencies:
- dependency-name: data-encoding
  dependency-version: 2.9.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-14 10:14:19 -04:00
katelyn martin 8a3a7aa072
chore(deps): group symbolic dependencies (#3863)
we use the `symbolic-common` and `symbolic-demangle` crates in our
dependency tree. these live in the same repo, here:
<https://github.com/getsentry/symbolic>

this commit introduces a "group" so that dependabot will upgrade them in
lockstep, rather than individually, such as in pull requests like
 #3853, #3852, #3857, #3858, or #3860.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-04-11 16:07:49 -04:00
dependabot[bot] 6bd80d4898
build(deps): bump symbolic-common from 12.15.1 to 12.15.3 (#3862)
Bumps [symbolic-common](https://github.com/getsentry/symbolic) from 12.15.1 to 12.15.3.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/commits/12.15.3)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-version: 12.15.3
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 10:04:42 -04:00
dependabot[bot] ab11b85fee
build(deps): bump cc from 1.2.18 to 1.2.19 (#3861)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.18 to 1.2.19.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.18...cc-v1.2.19)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.19
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 10:04:26 -04:00
dependabot[bot] bd859fdb69
build(deps): bump symbolic-demangle from 12.15.1 to 12.15.3 (#3860)
Bumps [symbolic-demangle](https://github.com/getsentry/symbolic) from 12.15.1 to 12.15.3.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/commits/12.15.3)

---
updated-dependencies:
- dependency-name: symbolic-demangle
  dependency-version: 12.15.3
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 10:04:17 -04:00
dependabot[bot] 36f1fac274
build(deps): bump rustls from 0.23.25 to 0.23.26 in the rustls group (#3859)
Bumps the rustls group with 1 update: [rustls](https://github.com/rustls/rustls).


Updates `rustls` from 0.23.25 to 0.23.26
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.25...v/0.23.26)

---
updated-dependencies:
- dependency-name: rustls
  dependency-version: 0.23.26
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: rustls
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 10:04:03 -04:00
dependabot[bot] 2f345f9aea
build(deps): bump symbolic-common from 12.15.0 to 12.15.1 (#3858)
Bumps [symbolic-common](https://github.com/getsentry/symbolic) from 12.15.0 to 12.15.1.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/commits)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-version: 12.15.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-10 09:55:34 -04:00
dependabot[bot] a9c123566f
build(deps): bump symbolic-demangle from 12.15.0 to 12.15.1 (#3857)
Bumps [symbolic-demangle](https://github.com/getsentry/symbolic) from 12.15.0 to 12.15.1.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/commits)

---
updated-dependencies:
- dependency-name: symbolic-demangle
  dependency-version: 12.15.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-10 09:55:24 -04:00
katelyn martin 6426c38906
fix(http/prom): record bodies when eos reached (#3856)
* chore(app/outbound): `linkerd-mock-http-body` test dependency

this adds a development dependency, so we can use this mock body type in
the outbound proxy's unit tests.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/outbound): additional http route metrics tests

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/outbound): additional grpc route metrics tests

Signed-off-by: katelyn martin <kate@buoyant.io>

* fix(http/prom): record bodies when eos reached

this commit fixes a bug discovered by @alpeb, which was introduced in
proxy v2.288.0.

> The associated metric is `outbound_http_route_request_statuses_total`:
>
> ```
> $ linkerd dg proxy-metrics -n booksapp deploy/webapp|rg outbound_http_route_request_statuses_total.*authors
> outbound_http_route_request_statuses_total{parent_group="core",parent_kind="Service",parent_namespace="booksapp",parent_name="authors",parent_port="7001",parent_section_name="",route_group="",route_kind="default",route_namespace="",route_name="http",hostname="",http_status="204",error=""} 5
> outbound_http_route_request_statuses_total{parent_group="core",parent_kind="Service",parent_namespace="booksapp",parent_name="authors",parent_port="7001",parent_section_name="",route_group="",route_kind="default",route_namespace="",route_name="http",hostname="",http_status="201",error="UNKNOWN"} 5
> outbound_http_route_request_statuses_total{parent_group="core",parent_kind="Service",parent_namespace="booksapp",parent_name="authors",parent_port="7001",parent_section_name="",route_group="",route_kind="default",route_namespace="",route_name="http",hostname="",http_status="200",error="UNKNOWN"} 10
> ```
>
> The problem was introduced in `edge-25.3.4`, with the proxy `v2.288.0`.
> Before that the metrics looked like:
>
> ```
> $ linkerd dg proxy-metrics -n booksapp deploy/webapp|rg outbound_http_route_request_statuses_total.*authors
> outbound_http_route_request_statuses_total{parent_group="core",parent_kind="Service",parent_namespace="booksapp",parent_name="authors",parent_port="7001",parent_section_name="",route_group="",route_kind="default",route_namespace="",route_name="http",hostname="",http_status="200",error=""} 193
> outbound_http_route_request_statuses_total{parent_group="core",parent_kind="Service",parent_namespace="booksapp",parent_name="authors",parent_port="7001",parent_section_name="",route_group="",route_kind="default",route_namespace="",route_name="http",hostname="",http_status="204",error=""} 96
> outbound_http_route_request_statuses_total{parent_group="core",parent_kind="Service",parent_namespace="booksapp",parent_name="authors",parent_port="7001",parent_section_name="",route_group="",route_kind="default",route_namespace="",route_name="http",hostname="",http_status="201",error=""} 96
> ```
>
> So the difference is the non-empty value for `error=UNKNOWN` even
> when `https_status` is 2xx, which `linkerd viz stat-outbound`
> interprets as failed requests.

in #3086 we introduced a suite of route- and backend-level metrics. that
subsystem contains a body middleware that will report itself as having
reached the end-of-stream by delegating directly down to its inner
body's `is_end_stream()` hint.

this is roughly correct, but is slightly distinct from the actual
invariant: a `linkerd_http_prom::record_response::ResponseBody<B>` must
call its `end_stream` helper to classify the outcome and increment the
corresponding time series in the
`outbound_http_route_request_statuses_total` metric family.

in #3504 we upgraded our hyper dependency. while doing so, we neglected
to include a call to `end_stream` if a data frame is yielded and the
inner body reports itself as having reached the end-of-stream.

this meant that instrumented bodies would be polled until the end is
reached, but were being dropped before a `None` was encountered.

this commit fixes this issue in two ways, to be defensive:

* invoke `end_stream()` if a non-trailers frame is yielded, and the
  inner body now reports itself as having ended. this restores the
  behavior in place prior to #3504. see the relevant component of that
  diff, here:
  <https://github.com/linkerd/linkerd2-proxy/pull/3504/files#diff-45d0bc344f76c111551a8eaf5d3f0e0c22ee6e6836a626e46402a6ae3cbc0035L262-R274>

* rather than delegating to the inner `<B as Body>::is_end_stream()`
  method, report the end-of-stream being reached by inspecting whether
  or not the inner response state has been taken. this is the state that
  directly indicates whether or not the `ResponseBody<B>` middleware is
  finished.

X-ref: #3504
X-ref: #3086
X-ref: linkerd/linkerd2#8733
Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-04-09 15:30:55 -04:00
dependabot[bot] 985580f9b5
build(deps): bump miniz_oxide from 0.8.7 to 0.8.8 (#3855)
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.8.7 to 0.8.8.
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/compare/0.8.7...0.8.8)

---
updated-dependencies:
- dependency-name: miniz_oxide
  dependency-version: 0.8.8
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 10:59:41 -04:00
dependabot[bot] ad7fcf2dfb
build(deps): bump crossbeam-channel from 0.5.14 to 0.5.15 (#3854)
Bumps [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) from 0.5.14 to 0.5.15.
- [Release notes](https://github.com/crossbeam-rs/crossbeam/releases)
- [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-channel-0.5.14...crossbeam-channel-0.5.15)

---
updated-dependencies:
- dependency-name: crossbeam-channel
  dependency-version: 0.5.15
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 10:59:35 -04:00
dependabot[bot] f6bbab6640
build(deps): bump symbolic-common from 12.14.1 to 12.15.0 (#3853)
Bumps [symbolic-common](https://github.com/getsentry/symbolic) from 12.14.1 to 12.15.0.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/commits)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-version: 12.15.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 10:59:28 -04:00
dependabot[bot] 5f2f8fbacd
build(deps): bump symbolic-demangle from 12.14.1 to 12.15.0 (#3852)
Bumps [symbolic-demangle](https://github.com/getsentry/symbolic) from 12.14.1 to 12.15.0.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/commits)

---
updated-dependencies:
- dependency-name: symbolic-demangle
  dependency-version: 12.15.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 10:59:20 -04:00
dependabot[bot] 096f547ffb
build(deps): bump tj-actions/changed-files from 46.0.4 to 46.0.5 (#3851)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 46.0.4 to 46.0.5.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](6cb76d07be...ed68ef82c0)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-version: 46.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 10:59:09 -04:00
dependabot[bot] abeb366500
build(deps): bump jiff from 0.2.5 to 0.2.6 (#3849)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.5 to 0.2.6.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.5...jiff-static-0.2.6)

---
updated-dependencies:
- dependency-name: jiff
  dependency-version: 0.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 12:05:56 -04:00
dependabot[bot] c17a6acee8
build(deps): bump hostname from 0.4.0 to 0.4.1 (#3850)
Bumps [hostname](https://github.com/svartalf/hostname) from 0.4.0 to 0.4.1.
- [Release notes](https://github.com/svartalf/hostname/releases)
- [Changelog](https://github.com/djc/hostname/blob/main/CHANGELOG.md)
- [Commits](https://github.com/svartalf/hostname/commits)

---
updated-dependencies:
- dependency-name: hostname
  dependency-version: 0.4.1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 12:05:23 -04:00
dependabot[bot] a9f7a9ae9d
build(deps): bump indexmap from 2.8.0 to 2.9.0 (#3848)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.8.0 to 2.9.0.
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.8.0...2.9.0)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 10:18:15 -04:00
dependabot[bot] 6de15c0a55
build(deps): bump tokio from 1.44.1 to 1.44.2 (#3847)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.44.1 to 1.44.2.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.44.1...tokio-1.44.2)

---
updated-dependencies:
- dependency-name: tokio
  dependency-version: 1.44.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 10:17:40 -04:00
dependabot[bot] 77837c5e45
build(deps): bump smallvec from 1.14.0 to 1.15.0 (#3846)
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: smallvec
  dependency-version: 1.15.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 10:17:17 -04:00
dependabot[bot] e6fee10099
build(deps): bump prettyplease from 0.2.31 to 0.2.32 (#3845)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.31 to 0.2.32.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.31...0.2.32)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-version: 0.2.32
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 10:17:00 -04:00
dependabot[bot] 52a30254c7
build(deps): bump errno from 0.3.10 to 0.3.11 (#3844)
Bumps [errno](https://github.com/lambda-fairy/rust-errno) from 0.3.10 to 0.3.11.
- [Release notes](https://github.com/lambda-fairy/rust-errno/releases)
- [Changelog](https://github.com/lambda-fairy/rust-errno/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lambda-fairy/rust-errno/compare/v0.3.10...v0.3.11)

---
updated-dependencies:
- dependency-name: errno
  dependency-version: 0.3.11
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 12:25:48 -04:00
dependabot[bot] fee5b9734a
build(deps): bump cc from 1.2.17 to 1.2.18 (#3843)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.17 to 1.2.18.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.17...cc-v1.2.18)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.18
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 15:55:47 +00:00
katelyn martin 33a177d054
chore(deps): add `tokio-boring` to dependabot group (#3842)
this adds `tokio-boring` to the `boring` group.

this will group these crates together and bump them in lockstep.

see, for example:
* #3838
* #3840

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-04-04 11:44:05 -04:00
dependabot[bot] 6cc16b430e
build(deps): bump tokio-boring from 4.15.0 to 4.16.0 (#3838)
Bumps [tokio-boring](https://github.com/cloudflare/boring) from 4.15.0 to 4.16.0.
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.15.0...v4.16.0)

---
updated-dependencies:
- dependency-name: tokio-boring
  dependency-version: 4.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 11:34:16 -04:00
dependabot[bot] 18109a447e
build(deps): bump opentelemetry in the opentelemetry group (#3837)
Bumps the opentelemetry group with 1 update: [opentelemetry](https://github.com/open-telemetry/opentelemetry-rust).


Updates `opentelemetry` from 0.29.0 to 0.29.1
- [Release notes](https://github.com/open-telemetry/opentelemetry-rust/releases)
- [Commits](https://github.com/open-telemetry/opentelemetry-rust/compare/opentelemetry-0.29.0...opentelemetry-0.29.1)

---
updated-dependencies:
- dependency-name: opentelemetry
  dependency-version: 0.29.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: opentelemetry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 11:03:32 -04:00
dependabot[bot] 05b4ab7314
build(deps): bump miniz_oxide from 0.8.5 to 0.8.7 (#3841)
Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.8.5 to 0.8.7.
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/compare/0.8.5...0.8.7)

---
updated-dependencies:
- dependency-name: miniz_oxide
  dependency-version: 0.8.7
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 10:51:20 -04:00
dependabot[bot] 483cd0d3ff
build(deps): bump tj-actions/changed-files (#3839)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from b74df86ccb65173a8e33ba5492ac1a2ca6b216fd to 6cb76d07bee4c9772c6882c06c37837bf82a04d3.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](b74df86ccb...6cb76d07be)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-version: 6cb76d07bee4c9772c6882c06c37837bf82a04d3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 10:50:18 -04:00
dependabot[bot] 5444732bab
build(deps): bump flate2 from 1.1.0 to 1.1.1 (#3835)
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.0...1.1.1)

---
updated-dependencies:
- dependency-name: flate2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 11:47:35 -04:00
katelyn martin 686934cec6
chore(proxy/http): use `hyper_util::rt::tokio::TokioExecutor` (#3833)
this commit removes the `linkerd-http-executor` crate, and replaces all
usage of its `TracingExecutor` type with the `TokioExecutor` type
provided by `hyper-util`.

this work is based upon hyperium/hyper-util#166. that change, included
in the 0.1.11 release, altered the `TokioExecutor` type so that it
propagates tracing context when the `tracing` feature is enabled.

with that change made, our `TracingExecutor` type is now redundant.

* https://github.com/hyperium/hyper-util/pull/166
* https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md#0111-2025-03-31

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-04-01 13:19:53 -04:00
katelyn martin c01e7e268a
feat(app,dns): add prometheus metrics to `Dns` (#3822)
this commit introduces a new metric family tracking the rate and outcome
of dns lookups made by the linkerd2 proxy. this metric family has three
labels, counting the number of DNS resolutions for each distinct
control plane client, by record type (A/AAAA or SRV), and by outcome
(success or failure).

this metric is named `control_dns_resolutions_total`.

this commit generally does this via the addition of some new interfaces
to `linkerd-dns`'s `Resolver` structure. the `resolve_addrs()` method is
extended to increment particular counters if they have been installed.

the `linkerd-app` crate's `Dns` type now encapsulates its resolver, and
callers acquire a new resolver by providing a client name to its
`resolver()` method. this uses the client name to construct label sets
and create the corresponding time series for each client.

once proxies with this patch are running, and the viz extension has been
installed, one can query this metric like so:

**nb:** this screenshot shows an early prototype, this metric has since
been renamed.

![linkerd-dns-prometheus-metrics](https://github.com/user-attachments/assets/3138dcfc-6800-4c0f-8215-61d84085032b)

this promQL query...

```
sum(rate(control_dns_resolutions_total[1m])) by (app,client,result) > 0
```

...will show the per-minute rate of dns lookups/failures across each
application workload, for each control-plane client, for each possible
outcome.

Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-04-01 16:02:17 +00:00
Oliver Gould c631974d97
feat(inbound): support unsafe authority labels via configuration (#3830)
In linkerd/linkerd2-proxy#3547, we removed unsafe authority labels. This was a
breaking change, since the behavior was considered unsafe.

To support a graceful migration, this change adds an environment configuration,
`LINKERD2_PROXY_INBOUND_AUTHORITY_LABELS=unsafe`, that reverts to the prior
behavior.

It may be configured in linkerd2 via the proxy.additionalEnv helm value.
2025-04-01 18:17:09 +03:00
dependabot[bot] f3b67eaaa7
build(deps): bump tj-actions/changed-files (#3831)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 27ae6b33eaed7bf87272fdeb9f1c54f9facc9d99 to b74df86ccb65173a8e33ba5492ac1a2ca6b216fd.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](27ae6b33ea...b74df86ccb)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 11:16:53 -04:00
dependabot[bot] c426634f6d
build(deps): bump hyper-util from 0.1.10 to 0.1.11 (#3832)
Bumps [hyper-util](https://github.com/hyperium/hyper-util) from 0.1.10 to 0.1.11.
- [Release notes](https://github.com/hyperium/hyper-util/releases)
- [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.10...v0.1.11)

---
updated-dependencies:
- dependency-name: hyper-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 11:16:00 -04:00
dependabot[bot] 652ab23578
build(deps): bump governor from 0.8.0 to 0.10.0 (#3817)
Bumps [governor](https://github.com/boinkor-net/governor) from 0.8.0 to 0.10.0.
- [Release notes](https://github.com/boinkor-net/governor/releases)
- [Changelog](https://github.com/boinkor-net/governor/blob/master/release.toml)
- [Commits](https://github.com/boinkor-net/governor/compare/v0.8.0...v0.10.0)

---
updated-dependencies:
- dependency-name: governor
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 18:58:17 +00:00
Oliver Gould 9d2df887a7
chore(deny): allow Zlib (#3829) 2025-03-31 14:43:45 -04:00
dependabot[bot] a3d854ee8e
build(deps): bump once_cell from 1.21.2 to 1.21.3 (#3826)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.21.2 to 1.21.3.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.21.2...v1.21.3)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 08:47:13 -07:00
dependabot[bot] 89971fc130
build(deps): bump socket2 from 0.5.8 to 0.5.9 (#3825)
Bumps [socket2](https://github.com/rust-lang/socket2) from 0.5.8 to 0.5.9.
- [Release notes](https://github.com/rust-lang/socket2/releases)
- [Changelog](https://github.com/rust-lang/socket2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/socket2/commits)

---
updated-dependencies:
- dependency-name: socket2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 08:46:57 -07:00
katelyn martin 523d3ed25d
chore(deps): group grpc dependabot groups (#3821)
* https://github.com/linkerd/linkerd2/blob/main/.github/dependabot.yml#L81-L86
* #3809
* https://github.com/linkerd/linkerd2-proxy-api/pull/455#discussion_r2017528014

tonic and prost are interconnected. we should bump them in lockstep.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-31 08:44:46 -07:00
Oliver Gould e0c4d42317
chore(deps): bump linkerd2-proxy-api from git to v0.16.0 (#3827) 2025-03-31 08:10:21 -07:00
Oliver Gould 2e4ca134b5
fix(ci): work around broken `linkerd install --crds` (#3828)
The latest edge doesn't properly install gateway API crds. This changes our
justfile to install the resources from the upstream release instead of the
Linkerd CLI.
2025-03-31 14:55:09 +00:00
katelyn martin cdfcbc10f0
nit(app): tweak debug event message (#3823)
this commit changes a message for a debug-level tracing event.

this block builds a trace collector. we can call it that, instead of the
more generic term "client". there are many clients being built here,
including identity, policy, and destination controller clients.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-27 15:34:00 -07:00
katelyn martin 0404a69250
nit(docs): fix broken intradoc links (#3820)
this commit fixes some broken links now that we have updated to the
latest 1.0 version of `http-body`.

this should address some warnings that can be seen in pull requests'
"files" tab in github. see, for example:
`https://github.com/linkerd/linkerd2-proxy/pull/3818/files`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-27 15:12:41 -07:00
katelyn martin ae8caa630b
refactor(app/core): remove unused dns configuration surface (#3819)
`LINKERD2_PROXY_RESOLV_CONF` is an environment variable that ostensibly
is used to set the path of the resolver configuration file.

this connects to a `resolv_conf_path` field in the application's dns
`Config` structure, but that field is never used.

because it is marked as public, this isn't caught by the compiler's dead
code analysis.

see `resolv.conf(5)` for more information.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-27 16:45:52 -04:00
dependabot[bot] df39864cea
build(deps): bump once_cell from 1.21.1 to 1.21.2 (#3818)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.21.1 to 1.21.2.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.21.1...v1.21.2)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-27 16:43:54 -04:00
katelyn martin 9300d3b4a5
chore(deps): dependabot group for unicode components (#3815)
* chore(deps): dependabot group for unicode components

this commit introduces a new dependabot group.

this will update all of the crates maintained by the icu4x organization
in lockstep. we depend upon these transitively to handle urls.

```
; cargo tree | rg icu_ | rg 'icu_\w*' --only-matching | sort | uniq
icu_collections
icu_locid
icu_locid_transform
icu_locid_transform_data
icu_normalizer
icu_normalizer_data
icu_properties
icu_properties_data
icu_provider
icu_provider_macros
```

see:

- https://docs.rs/icu/latest/icu/
- https://icu.unicode.org/
- https://github.com/orgs/unicode-org/repositories?type=all
- https://crates.io/crates/idna
- #3811
- #3812
- #3813

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit: alphabetize

Signed-off-by: katelyn martin <kate@buoyant.io>

* review: use a glob

Co-authored-by: Oliver Gould <ver@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-03-27 14:55:43 -04:00
katelyn martin 92e55e46f1
chore(deps): update unicode dependencies (#3816)
this commit updates our `icu_*` dependencies.

see:
* #3811
* #3812
* #3813
* #3815

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-27 14:54:19 -04:00
katelyn martin 6691c16b79
nit(proxy-resolve): address `XXX` comment (#3814)
this commit addresses a todo comment in the `linkerd-proxy-resolve`
crate. this comment mentioned that a `match` block was originally an `if
let` block. a clippy lint is locally ignored as well, regarding `match`
statements with a single pattern.

contrary to the comment, `if let` *does* work with pin projection, as of
today.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-27 14:54:02 -04:00
katelyn martin 3c2d5ddfc3
chore(deps): add `tonic` dependabot group (#3809)
this commit adds a group to the dependabot configuration.

this will mean that dependabot updates `tonic` and `tonic-build` in
lockstep.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-26 16:13:53 -04:00
dependabot[bot] 9ef862b8c7
build(deps): bump rustls-webpki in the rustls group (#3808)
Bumps the rustls group with 1 update: [rustls-webpki](https://github.com/rustls/webpki).


Updates `rustls-webpki` from 0.103.0 to 0.103.1
- [Release notes](https://github.com/rustls/webpki/releases)
- [Commits](https://github.com/rustls/webpki/compare/v/0.103.0...v/0.103.1)

---
updated-dependencies:
- dependency-name: rustls-webpki
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rustls
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-26 10:58:28 -04:00
katelyn martin a3ce71954e
fix(dns-resolve): add a lower-bound TTL for dns refreshing (#3807)
DNS servers may return extremely low TTLs in some cases. When we're polling DNS to power a load balancer, we need to enforce a minimum duration to prevent tight-looping DNS queries.

This change adds a 5s minimum time between DNS lookups when resolving control plane components.

fixes linkerd/linkerd2#13508
2025-03-25 16:37:38 -07:00
dependabot[bot] 135a7352ae
build(deps): bump log from 0.4.26 to 0.4.27 (#3806)
Bumps [log](https://github.com/rust-lang/log) from 0.4.26 to 0.4.27.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.26...0.4.27)

---
updated-dependencies:
- dependency-name: log
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 10:44:51 -04:00
dependabot[bot] 85d1d31f06
build(deps): bump deranged from 0.4.0 to 0.4.1 (#3805)
* build(deps): bump deranged from 0.4.0 to 0.4.1

Bumps [deranged](https://github.com/jhpratt/deranged) from 0.4.0 to 0.4.1.
- [Commits](https://github.com/jhpratt/deranged/commits)

---
updated-dependencies:
- dependency-name: deranged
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(proxy/tap): fix inference error

https://github.com/jhpratt/deranged/issues/19

`deranged` added some additional interfaces in 0.4.1 that seem to affect
this `Into<T>` invocation. use `From::from` instead, so we can
explicitly indicate that we wish to convert this into an integer for
comparison.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: katelyn martin <kate@buoyant.io>
2025-03-24 11:16:37 -04:00
dependabot[bot] a7c12ea54c
build(deps): bump time from 0.3.40 to 0.3.41 (#3804)
Bumps [time](https://github.com/time-rs/time) from 0.3.40 to 0.3.41.
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.40...v0.3.41)

---
updated-dependencies:
- dependency-name: time
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 06:53:24 -07:00
dependabot[bot] 59e330f561
build(deps): bump jiff from 0.2.4 to 0.2.5 (#3803)
Bumps [jiff](https://github.com/BurntSushi/jiff) from 0.2.4 to 0.2.5.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-static-0.2.4...jiff-static-0.2.5)

---
updated-dependencies:
- dependency-name: jiff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 06:53:02 -07:00
dependabot[bot] f20851ee0b
build(deps): bump jiff-tzdb from 0.1.3 to 0.1.4 (#3802)
Bumps [jiff-tzdb](https://github.com/BurntSushi/jiff) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/BurntSushi/jiff/releases)
- [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/jiff/compare/jiff-tzdb-0.1.3...jiff-tzdb-0.1.4)

---
updated-dependencies:
- dependency-name: jiff-tzdb
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 06:52:48 -07:00
dependabot[bot] a92e6e97e7
build(deps): bump the opentelemetry group with 2 updates (#3801)
Bumps the opentelemetry group with 2 updates: [opentelemetry](https://github.com/open-telemetry/opentelemetry-rust) and [opentelemetry_sdk](https://github.com/open-telemetry/opentelemetry-rust).


Updates `opentelemetry` from 0.28.0 to 0.29.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-rust/releases)
- [Commits](https://github.com/open-telemetry/opentelemetry-rust/compare/opentelemetry-0.28.0...opentelemetry-0.29.0)

Updates `opentelemetry_sdk` from 0.28.0 to 0.29.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-rust/releases)
- [Commits](https://github.com/open-telemetry/opentelemetry-rust/compare/opentelemetry_sdk-0.28.0...opentelemetry_sdk-0.29.0)

---
updated-dependencies:
- dependency-name: opentelemetry
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry
- dependency-name: opentelemetry_sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 06:47:06 -07:00
dependabot[bot] 2108f3433e
build(deps): bump tj-actions/changed-files (#3800)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 6482371e862961013f9584015cf362c4f664b20c to 27ae6b33eaed7bf87272fdeb9f1c54f9facc9d99.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](6482371e86...27ae6b33ea)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 06:45:04 -07:00
Oliver Gould 9f4c019844
fix(app): avoid unused import on non-linux builds (#3799) 2025-03-21 10:53:16 -07:00
Oliver Gould 41b93cb805
chore(ci): disable unnecessary k3s components (#3798)
We can run our testing k3d cluster with minimal components enabled. This will
speed up the cluster creation and deletion process (i.e. especially in CI).
2025-03-21 17:15:17 +00:00
katelyn martin 76d969544f
chore(deps): upgrade to tower 0.5 (#3744)
* chore(deps)!: upgrade to tower 0.5

this commit updates our tower dependency from 0.4 to 0.5.

note that this commit does not affect the `tower-service` and
`tower-layer` crates, reëxported by `tower` itself. the `Service<T>`
trait and the closely related `Layer<S>` trait have not been changed.

the `tower` crate's utilities have changed in various ways, some of
particular note for the linkerd2 proxy. see these items, excerpted from
the tower changelog:

- **retry**: **Breaking Change** `retry::Policy::retry` now accepts `&mut Req` and `&mut Res` instead of the previous mutable versions. This
  increases the flexibility of the retry policy. To update, update your method signature to include `mut` for both parameters. ([tower-rs/tower#584])
- **retry**: **Breaking Change** Change Policy to accept &mut self ([tower-rs/tower#681])
- **retry**: **Breaking Change** `Budget` is now a trait. This allows end-users to implement their own budget and bucket implementations. ([tower-rs/tower#703])
- **util**: **Breaking Change** `Either::A` and `Either::B` have been renamed `Either::Left` and `Either::Right`, respectively. ([tower-rs/tower#637])
- **util**: **Breaking Change** `Either` now requires its two services to have the same error type. ([tower-rs/tower#637])
- **util**: **Breaking Change** `Either` no longer implemenmts `Future`. ([tower-rs/tower#637])
- **buffer**: **Breaking Change** `Buffer<S, Request>` is now generic over `Buffer<Request, S::Future>.` ([tower-rs/tower#654])

see:

* <https://github.com/tower-rs/tower/pull/584>
* <https://github.com/tower-rs/tower/pull/681>
* <https://github.com/tower-rs/tower/pull/703>
* <https://github.com/tower-rs/tower/pull/637>
* <https://github.com/tower-rs/tower/pull/654>

the `Either` trait bounds are particularly impactful for us. because
this runs counter to how we treat errors (skewing towards boxed errors,
in general), we temporarily vendor a version of `Either` from the 0.4
release, whose variants have been renamed to match the 0.5 interface.

updating to box the inner `A` and `B` services' errors, so we satiate
the new `A::Error = B::Error` bounds, can be addressed as a follow-on.
that's intentionally left as a separate change, due to the net size of
our patchset between this branch and #3504.

* <https://github.com/tower-rs/tower/compare/v0.4.x...master>
* <https://github.com/tower-rs/tower/blob/master/tower/CHANGELOG.md>

this work is based upon #3504. for more information, see:

* https://github.com/linkerd/linkerd2/issues/8733
* https://github.com/linkerd/linkerd2-proxy/pull/3504

Signed-off-by: katelyn martin <kate@buoyant.io>
X-Ref: https://github.com/tower-rs/tower/pull/815
X-Ref: https://github.com/tower-rs/tower/pull/817
X-Ref: https://github.com/tower-rs/tower/pull/818
X-Ref: https://github.com/tower-rs/tower/pull/819

* fix(stack/loadshed): update test affected by tower-rs/tower#635

this commit updates a test that was affected by breaking changes in
tower's `Buffer` middleware. see this excerpt from the description of
that change:

> I had to change some of the integration tests slightly as part of this
> change. This is because the buffer implementation using semaphore
> permits is _very subtly_ different from one using a bounded channel. In
> the `Semaphore`-based implementation, a semaphore permit is stored in
> the `Message` struct sent over the channel. This is so that the capacity
> is used as long as the message is in flight. However, when the worker
> task is processing a message that's been recieved from the channel,
> the permit is still not dropped. Essentially, the one message actively
> held by the worker task _also_ occupies one "slot" of capacity, so the
> actual channel capacity is one less than the value passed to the
> constructor, _once the first request has been sent to the worker_. The
> bounded MPSC changed this behavior so that capacity is only occupied
> while a request is actually in the channel, which broke some tests
> that relied on the old (and technically wrong) behavior.

bear particular attention to this:

> The bounded MPSC changed this behavior so that capacity is only
> occupied while a request is actually in the channel, which broke some
> tests that relied on the old (and technically wrong) behavior.

that pr adds an additional message to the channel in tests exercising
the laod-shedding behavior, on account of the previous (incorrect)
behavior.

https://github.com/tower-rs/tower/pull/635/files#r797108274

this commit performs the same change for our corresponding test, adding
an additional `ready()` call before we hit the buffer's limit.

Signed-off-by: katelyn martin <kate@buoyant.io>

* review: use vendored `Either` for consistency

https://github.com/linkerd/linkerd2-proxy/pull/3744#discussion_r1999878537

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-21 17:08:34 +00:00
Oliver Gould bab244210e
chore(just): set installGatewayAPI in CRD install (#3797) 2025-03-21 12:59:20 -04:00
Alejandro Pedraza f1768a3044
fix(transport): repair IPv6 support (#3793)
In #3626, we refactored the origin_dst determination logic to utilize
socket2 calls. However, this change inadvertently disrupted IPv6 and
dual-stack support, causing the server to fail to start when deployed on
such network configurations:

```
WARN ThreadId(01) inbound: linkerd_app_core::serve: Server failed to accept connection error=No such file or directory (os error 2)
```

This change reintroduces detection of the current network family,
calling socket2's `original_dst()` or `original_dst_ipv6()` depending on
the case.

Tested fine in both IPv6 and dual-stack Kind clusters.
2025-03-21 09:54:12 -07:00
katelyn martin 76d4181499
chore(deps)!: upgrade to hyper 1.x (#3504)
##  chore(deps): upgrade to hyperium 1.x crates

this branch performs an exciting upgrade for our proxy.

this branch upgrades a number of our dependencies so that we use the 1.0
release family of the `hyper` http framework, and its ecosystem. see the
[v1.0 announcement][hyper-v1] for more information.

this branch upgrades the following dependencies:

* `h2`: 0.3 -> 0.4
* `http`: 0.2 -> 1
* `http-body`: 0.4 -> 1
* `hyper`: 0.14.32 -> 1
* `prost`: 0.12 -> 0.13
* `prost-build`: 0.12 -> 0.13
* `prost-types`: 0.12 -> 0.13
* `tonic`: 0.10 -> 0.12
* `tonic-build`: 0.10 -> 0.12

a `hyper-util` dependency is added, which provides among other things,
legacy-compatible interfaces such as `hyper_util::client::legacy::Client`, or
glue to use `hyper` with the tokio runtime.

see <https://docs.rs/hyper-util/latest/hyper_util/> for more information.

a `http-body-util` dependency is added, which provides a `BodyExt` trait and a
channel-backed body for use in unit tests. the `deprecated` feature flag that
was active on our `0.14` hyper dependency has been removed, along with the
`stream` and `runtime` feature flags.

the `linkerd2-proxy-api` dependency is updated. see:
<https://github.com/linkerd/linkerd2-proxy-api/pull/421>

### 📝 notes for review

bear particular attention to changes involving `http_body::Body` middleware.

the change from two separate `poll_data()` and `poll_trailers()` functions,
to a single `poll_frame()` method, induces some subtle changes to various
pieces of middleware.

also bear in mind that failing to set a timer, in our case
`hyper_util::rt::TokioTimer`, can cause http/2 clients, or http/1 and http/2
servers, to panic. make sure that any uses of
`hyper::server::conn::http1::Builder`, `hyper::client::conn::http1::Builder`,
or `hyper::client::conn::http2::Builder` install a timer.

###  breaking change: `l5d-proxy-error` values

the `l5d-proxy-error` header can be examined to observe the cause of proxy
errors encountered when sending meshed traffic. by virtue of this using a newer
`hyper` client in the proxy, some error messages may in turn look different.
for example, an error like `"connect timed out after 1s"` may now appear as
`"client error (Connect)"`.

### 📚 other notes

this work, by virtue of touching so many parts of the system, is carried out
in distinct commits. an initial commit upgrades the dependencies at th
workspace level. subsequent commits will not compile if the `--workspace` flag
is provided, but the intent of this branch is to update each crate
individually.

use commands like, e.g. `cargo check --tests -p linkerd-proxy-http` to build
particular crates at intermediate commits within this branch.

this commit is also only the final leaf in an _extended_ line of work. this
has been done to mitigate the effort of reviewing this change, and the risk of
churn in the event of any unanticipated errors. see the top-level comment in
https://github.com/linkerd/linkerd2/issues/8733 for an overview of all of the
work that brought us to this juncture.

[hyper-v1]: https://seanmonstar.com/blog/hyper-v1/

---

* chore(deps): upgrade to hyper 1.x

note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <https://github.com/linkerd/linkerd2/issues/8733>.

see also:

* https://github.com/linkerd/linkerd2-proxy/pull/3379
* https://github.com/linkerd/linkerd2-proxy/pull/3380
* https://github.com/linkerd/linkerd2-proxy/pull/3382
* https://github.com/linkerd/linkerd2-proxy/pull/3405
* https://github.com/hyperium/hyper/pull/3796
* https://github.com/linkerd/linkerd2-proxy/pull/3411
* https://github.com/linkerd/linkerd2-proxy/pull/3421
* https://github.com/linkerd/linkerd2-proxy/pull/3427
* https://github.com/linkerd/linkerd2-proxy/pull/3428
* https://github.com/linkerd/linkerd2-proxy/pull/3432
* https://github.com/linkerd/linkerd2-proxy/pull/3433
* https://github.com/linkerd/linkerd2-proxy/pull/3444
* https://github.com/linkerd/linkerd2-proxy/pull/3445
* https://github.com/linkerd/linkerd2-proxy/pull/3454
* https://github.com/linkerd/linkerd2-proxy/pull/3455
* https://github.com/linkerd/linkerd2-proxy/pull/3456
* https://github.com/linkerd/linkerd2-proxy/pull/3457
* https://github.com/linkerd/linkerd2-proxy/pull/3461
* https://github.com/linkerd/linkerd2-proxy/pull/3459
* https://github.com/linkerd/linkerd2-proxy/pull/3465
* https://github.com/linkerd/linkerd2-proxy/pull/3466
* https://github.com/linkerd/linkerd2-proxy/pull/3467
* https://github.com/linkerd/linkerd2-proxy/pull/3468
* https://github.com/linkerd/linkerd2-proxy-api/pull/421
* https://github.com/linkerd/linkerd2/pull/13492
* https://github.com/linkerd/linkerd2/pull/13493
* https://github.com/hyperium/hyper/pull/3816
* https://github.com/linkerd/linkerd2-proxy/pull/3472
* https://github.com/linkerd/linkerd2-proxy/pull/3473
* https://github.com/linkerd/linkerd2-proxy/pull/3479
* https://github.com/tokio-rs/tokio/pull/7059
* https://github.com/linkerd/linkerd2-proxy/pull/3509
* https://github.com/hyperium/http-body/pull/140/
* https://github.com/linkerd/linkerd2-proxy/pull/3515
* https://github.com/hyperium/http-body/pull/141/
* https://github.com/linkerd/linkerd2-proxy/pull/3530
* https://github.com/linkerd/linkerd2-proxy/pull/3531
* https://github.com/linkerd/linkerd2-proxy/pull/3540
* https://github.com/linkerd/linkerd2-proxy/pull/3556
* https://github.com/linkerd/linkerd2-proxy/pull/3558
* https://github.com/linkerd/linkerd2-proxy/pull/3559
* https://github.com/linkerd/linkerd2-proxy/pull/3564
* https://github.com/linkerd/linkerd2-proxy/pull/3567
* https://github.com/linkerd/linkerd2-proxy/pull/3573
* https://github.com/linkerd/linkerd2-proxy/pull/3583
* https://github.com/hyperium/http-body/pull/144
* https://github.com/linkerd/linkerd2-proxy/pull/3585
* https://github.com/linkerd/linkerd2-proxy/pull/3586
* https://github.com/linkerd/linkerd2-proxy/pull/3597
* https://github.com/linkerd/linkerd2-proxy/pull/3598
* https://github.com/linkerd/linkerd2-proxy/pull/3611
* https://github.com/linkerd/linkerd2-proxy/pull/3614
* https://github.com/linkerd/linkerd2-proxy/pull/3615
* https://github.com/linkerd/linkerd2-proxy/pull/3616
* https://github.com/linkerd/linkerd2-proxy/pull/3647
* https://github.com/linkerd/linkerd2-proxy/pull/3651
* https://github.com/linkerd/linkerd2-proxy/pull/3653
* https://github.com/linkerd/linkerd2-proxy/pull/3654
* https://github.com/linkerd/linkerd2-proxy/pull/3655
* https://github.com/linkerd/linkerd2-proxy/pull/3656
* https://github.com/linkerd/linkerd2-proxy/pull/3657
* https://github.com/linkerd/linkerd2-proxy/pull/3660
* https://github.com/linkerd/linkerd2-proxy/pull/3671
* https://github.com/linkerd/linkerd2-proxy/pull/3672
* https://github.com/linkerd/linkerd2-proxy/pull/3673
* https://github.com/linkerd/linkerd2-proxy/pull/3676
* https://github.com/hyperium/http-body/pull/147
* https://github.com/linkerd/linkerd2-proxy/pull/3692
* https://github.com/linkerd/linkerd2-proxy/pull/3699
* https://github.com/linkerd/linkerd2-proxy/pull/3700
* https://github.com/linkerd/linkerd2-proxy/pull/3701
* https://github.com/linkerd/linkerd2-proxy/pull/3708
* https://github.com/linkerd/drain-rs/pull/36
* https://github.com/linkerd/linkerd2-proxy/pull/3715
* https://github.com/linkerd/linkerd2-proxy/pull/3717
* https://github.com/eminence/procfs/pull/340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/box): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(hyper-balance): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/retain): ugrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/stream-timeouts): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/classify): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/upgrade): upgrade to hyper 1.x

NOTE: there is a comment noting that the upgrade middleware does not
expect to be cloneable. it is unfortunately, however, at odds with the
new bounds expected of extensions.

so, `Http11Upgrade` is now Clone'able, but a comment is left in place
noting this weakened invariant.

it's worth investigating how upgrades have changed since, in more
detail, but for the current moment we are interested in being
especially conservative about changing behavior, and focusing on api
changes like `Body::poll_frame(..)`.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(metrics): upgrade to hyper 1.x

a brief note; this commit happened to tickle an unfortunate sharp edge
in `BoxBody` and `Full`'s respective constructors. type inference could
not figure out how to construct the body, so we refrain from boxing the
response body now.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/metrics): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/prom): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/insert): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/retry): deprecate linkerd-http-body-compat

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(mock/http-body): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/retry): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(proxy/tap): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(proxy/http): update to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/core): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/test): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/admin): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/outbound): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/inbound): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/integration): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app): upgrade to hyper 1.x

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(transport-header): update generated code

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(spiffe-proto): update generated code

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(opencensus-proto): update generated code

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(opentelemetry-proto): update generated code

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(deny.toml): update cargo-deny directives

this commit updates the contents of `deny.toml`.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore: `compile` has been renamed to `compile_protos`

this addresses deprecation warnings, updating calls to a function that
has since been renamed.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(deps): remove `linkerd-http-body-compat` dependencies

this commit removes this crate, which we added to future proof code for
this upgrade, from its dependents.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/body-compat): remove `linkerd-http-body-compat` crate

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(deps): update to drain 0.2.1

see https://github.com/linkerd/drain-rs/pull/41.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-21 12:53:11 -04:00
dependabot[bot] a41642a7fd
build(deps): bump cc from 1.2.16 to 1.2.17 (#3794)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.16 to 1.2.17.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.16...cc-v1.2.17)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 07:13:33 -07:00
dependabot[bot] 4de4ab12ce
build(deps): bump backtrace from 0.3.73 to 0.3.74 (#3795)
Bumps [backtrace](https://github.com/rust-lang/backtrace-rs) from 0.3.73 to 0.3.74.
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.73...0.3.74)

---
updated-dependencies:
- dependency-name: backtrace
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 07:13:21 -07:00
dependabot[bot] 97adbd47ae
build(deps): bump Swatinem/rust-cache from 2.7.7 to 2.7.8 (#3780)
Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.7.7 to 2.7.8.
- [Release notes](https://github.com/swatinem/rust-cache/releases)
- [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md)
- [Commits](f0deed1e0e...9d47c6ad4b)

---
updated-dependencies:
- dependency-name: Swatinem/rust-cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 12:21:17 -07:00
dependabot[bot] 869e420733
build(deps): bump actions/download-artifact from 4.2.0 to 4.2.1 (#3789)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](b14cf4c926...95815c38cf)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 12:20:59 -07:00
dependabot[bot] bd4f430740
build(deps): bump actions/upload-artifact from 4.6.1 to 4.6.2 (#3788)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.1 to 4.6.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](4cec3d8aa0...ea165f8d65)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 12:20:44 -07:00
katelyn martin 6a5cce8854
nit: golf `NameRef::try_from_ascii_str()` (#3786)
this golfs down the return expression in
`NameRef::try_from_ascii_str()`.

rather than binding our `s` to a temporary variable, in order to return
a `Self(s)` result, we can take the same result and use `Result::map` to
convert a `Result<&'a str, InvalidName>` to a
`Result<NameRef<'a>, InvalidName>`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-20 12:12:22 -07:00
dependabot[bot] acbea26364
build(deps): bump tj-actions/changed-files (#3790)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 0b975f61488402a699abcebd6a1e25924cf85218 to 6482371e862961013f9584015cf362c4f664b20c.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](0b975f6148...6482371e86)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 11:07:47 -04:00
dependabot[bot] 7f5c42a2b2
build(deps): bump loom from 0.7.1 to 0.7.2 (#3791)
Bumps [loom](https://github.com/tokio-rs/loom) from 0.7.1 to 0.7.2.
- [Release notes](https://github.com/tokio-rs/loom/releases)
- [Changelog](https://github.com/tokio-rs/loom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/loom/commits)

---
updated-dependencies:
- dependency-name: loom
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 11:07:25 -04:00
dependabot[bot] 7caef34cda
build(deps): bump tempfile from 3.19.0 to 3.19.1 (#3792)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.19.0 to 3.19.1.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.19.0...v3.19.1)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 11:07:11 -04:00
katelyn martin 03e9adb489
chore(dns): upgrade to `hickory-resolver` v0.25 (#3787)
* build(deps): bump the hickory group with 2 updates

Bumps the hickory group with 2 updates: [hickory-resolver](https://github.com/hickory-dns/hickory-dns) and [hickory-proto](https://github.com/hickory-dns/hickory-dns).


Updates `hickory-resolver` from 0.24.4 to 0.25.1
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/main/OLD-CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.4...v0.25.1)

Updates `hickory-proto` from 0.24.4 to 0.25.1
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/main/OLD-CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.4...v0.25.1)

---
updated-dependencies:
- dependency-name: hickory-resolver
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: hickory
- dependency-name: hickory-proto
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: hickory
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(dns): address breaking changes in `hickory-resolver`

see also #3782.

this commit addresses breaking changes in the v0.25.0 release of
`hickory-resolver`, used by our `linkerd-dns` crate to handle DNS
resolution.

see the release notes, here:
<https://github.com/hickory-dns/hickory-dns/releases/tag/v0.25.0>

> 0.25.0 represents a large release for the Hickory DNS project. Over 14
> months since 0.24.0, we've [..] addressed a number of findings from our
> first security audit.

changes that are relevant to us include:

> * Support for TLS using native-tls or OpenSSL has been removed. We now
>   only provide first-party support for rustls (0.23, for DNS over TLS,
>   HTTP/2, QUIC and HTTP/3). We support ring or aws-lc-rs for
>   cryptographic operations both for DNSSEC and TLS. The
>   dns-over-rustls,dns-over-native-tls, dns-over-openssl,
>   dns-over-https-rustls, dns-over-https, dns-over-quic and dns-over-h3
>   features have been removed in favor of a set of
>   {tls,https,quic,h3}-{aws-lc-rs,ring} features across our library
>   crates.
>
> * The synchronous API in the resolver and client crates, which
>   previously provided a thin partial wrapper over the asynchronous
>   API, has been removed. Downstream users will have to migrate to the
>   asynchronous API.
>
> * Error types are now exposed directly in the crate roots.

this commit updates references to the
`hickory_resolver::error::ResolveError` error with
`hickory_resolver::ResolveError` now that the errors submodule is
private. (hickory-dns/hickory-dns#2530)

this commit replaces references to
`hickory_resolver::TokioAsyncResolver` with its new name,
`hickory_resolver::TokioResolver`. (hickory-dns/hickory-dns#2521)

this commit inspects "no records found" errors according to the new api.
this particular change isn't especially documented, explicitly, but
occurred in hickory-dns/hickory-dns#2094. see in particular, in that
respect, corresponding changes in the upstream repo's own code. for
example: https://github.com/hickory-dns/hickory-dns/pull/2094/files#diff-330847b46040a30d449f85e8a804bea085f0974d3cba80d79d83acc56f33542dL176-R178

```diff
-  match error.kind() {
-       ResolveErrorKind::NoRecordsFound { query, soa, .. } => {
+   match error.proto().map(ProtoError::kind) {
+       Some(ProtoErrorKind::NoRecordsFound { query, soa, .. }) => {
```

there is a small pull request being proposed upstream to introduce a
`Builder::with_options()` method, which would make our construction of a
dns resolver marginally more idiomatic. this however, is not a blocker,
by any means.

X-Ref: hickory-dns/hickory-dns#2521
X-Ref: hickory-dns/hickory-dns#2830
X-Ref: hickory-dns/hickory-dns#2094
X-Ref: hickory-dns/hickory-dns#2877
Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 22:00:17 -04:00
dependabot[bot] 924403f62c
build(deps): bump actions/download-artifact from 4.1.9 to 4.2.0 (#3781)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.9 to 4.2.0.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](cc20338598...b14cf4c926)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 11:37:37 -04:00
dependabot[bot] 949cd5625c
build(deps): bump prettyplease from 0.2.30 to 0.2.31 (#3784)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.30 to 0.2.31.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.30...0.2.31)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 11:30:01 -04:00
dependabot[bot] a16235b937
build(deps): bump tokio from 1.43.0 to 1.44.1 (#3783)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.43.0 to 1.44.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.43.0...tokio-1.44.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 11:29:46 -04:00
Zahari Dichev a961efc883
chore(ci): add windows release target to relase matrix (#3771)
This PR adds os param to our package job in the release workflow.
This allows us to build and release Windows artifacts.

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2025-03-18 15:45:54 -07:00
katelyn martin 04d86a0375
refactor(http/upgrade): remove `HttpConnect` extension (#3779)
this branch is motivated by [review feedback](https://github.com/linkerd/linkerd2-proxy/pull/3504#discussion_r1999706761) from #3504. see
linkerd/linkerd2#8733 for more information on upgrading `hyper`. there,
we asked:

> I wonder if we should be a little more defensive about cloning [`HttpConnect`]. What does cloning it mean? When handling a CONNECT request, we can't clone the request, really. (Technically, we can't clone the body, but practically, it means we can't clone the request). Can we easily track whether this was accidentally cloned (i.e. with a custom Clone impl or Arc or some such) and validate at runtime (i.e., in proxy::http::h1) that everything is copacetic?

`linkerd-http-upgrade` provides a `HttpConnect` type that is intended
for use as a response extension. this commit performs a refactor,
removing this type.

we use this extension in a single piece of tower middleware. typically,
these sorts of extensions are intended for e.g. passing state between
distinct layers of tower middleware, or otherwise facilitating
extensions to the HTTP family of protocols.

this extension is only constructed and subsequently referenced within a
single file, in the `linkerd_proxy_http::http::h1::Client`. we can
perform the same task by using the `is_http_connect` boolean we use to
conditionally insert this extension.

then, this branch removes a helper function for a computation whose
amortization is no longer as helpful. now that we are passing
`is_http_connect` down into this function, we are no longer inspecting
the response's extensions. because of that, the only work to do is to
check the status code, which is a very cheap comparison.

this also restates an `if version != HTTP_11 { .. }` conditional block as
a match statement. this is a code motion change, none of the inner blocks
are changed.

reviewers are encouraged to examine this branch commit-by-commit; because
of the sensitivity of this change, this refactor is performed in small,
methodical changes.

for posterity, i've run the linkerd/linkerd2 test suite against this branch, as of
57dd7f4a60.

---

* refactor(http/upgrade): remove `HttpConnect` extension

`linkerd-http-upgrade` provides a `HttpConnect` type that is intended
for use as a response extension. this commit performs a refactor,
removing this type.

we use this extension in a single piece of tower middleware. typically,
these sorts of extensions are intended for e.g. passing state between
distinct layers of tower middleware, or otherwise facilitating
extensions to the HTTP family of protocols.

this extension is only constructed and subsequently referenced within a
single file, in the `linkerd_proxy_http::http::h1::Client`. we can
perform the same task by using the `is_http_connect` boolean we use to
conditionally insert this extension.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(proxy/http): fold helper function

this removes a helper function for a computation whose amortization is
no longer as helpful.

now that we are passing `is_http_connect` down into this function, we
are no longer inspecting the response's extensions. because of that, the
only work to do is to check the status code, which is a very cheap
comparison.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(proxy/http): match on response status

this commit refactors a sequence of conditional blocks in a helper
function used to identity HTTP/1.1 upgrades.

this commit replaces this sequence of conditional blocks with a match
statement.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(proxy/http): rename `res` to `rsp`

we follow a convention where we tend to name responses `rsp`, not `res`
or `resp`. this commit applies that convention to this helper function.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(proxy/http): import `Version`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(proxy/http): match on http version

this restates an `if version != HTTP_11 { .. }` conditional block as a
match statement.

this is a code motion change, none of the inner blocks are changed.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(proxy/http): add comments on http/1.1

this commit adds a brief comment noting that upgrades are a concept
specific to http/1.1.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-18 18:42:01 -04:00
dependabot[bot] 13478ae70a
build(deps): bump tj-actions/changed-files (#3777)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 9200e69727eb73eb060652b19946b8a2fdfb654b to 0b975f61488402a699abcebd6a1e25924cf85218.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](9200e69727...0b975f6148)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 12:54:48 -07:00
Zahari Dichev 61588895f7
chore(just): add .exe extension to windows binaries (#3769)
Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2025-03-18 12:34:09 -07:00
dependabot[bot] 912bacb7c5
build(deps): bump itoa from 1.0.14 to 1.0.15 (#3773)
Bumps [itoa](https://github.com/dtolnay/itoa) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/dtolnay/itoa/releases)
- [Commits](https://github.com/dtolnay/itoa/compare/1.0.14...1.0.15)

---
updated-dependencies:
- dependency-name: itoa
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 11:00:53 -04:00
dependabot[bot] 5da8af300e
build(deps): bump time from 0.3.39 to 0.3.40 (#3774)
Bumps [time](https://github.com/time-rs/time) from 0.3.39 to 0.3.40.
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.39...v0.3.40)

---
updated-dependencies:
- dependency-name: time
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 11:00:43 -04:00
dependabot[bot] 487377c888
build(deps): bump widestring from 1.1.0 to 1.2.0 (#3775)
Bumps [widestring](https://github.com/starkat99/widestring-rs) from 1.1.0 to 1.2.0.
- [Release notes](https://github.com/starkat99/widestring-rs/releases)
- [Changelog](https://github.com/starkat99/widestring-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/starkat99/widestring-rs/compare/v1.1.0...v1.2.0)

---
updated-dependencies:
- dependency-name: widestring
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 11:00:29 -04:00
dependabot[bot] c83a2a1ac6
build(deps): bump aligned-vec from 0.6.2 to 0.6.4 (#3776)
Bumps [aligned-vec](https://github.com/sarah-ek/aligned-vec) from 0.6.2 to 0.6.4.
- [Commits](https://github.com/sarah-ek/aligned-vec/compare/v0.6.2...v0.6.4)

---
updated-dependencies:
- dependency-name: aligned-vec
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 10:59:25 -04:00
dependabot[bot] 396cfcec2f
build(deps): bump rustls from 0.23.24 to 0.23.25 in the rustls group (#3772)
Bumps the rustls group with 1 update: [rustls](https://github.com/rustls/rustls).


Updates `rustls` from 0.23.24 to 0.23.25
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.24...v/0.23.25)

---
updated-dependencies:
- dependency-name: rustls
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: rustls
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 10:58:33 -04:00
Scott Fleener 65db3dd927
feat(policy): Allow outbound hostname metrics (#3770)
Outbound hostname metrics were recently disabled. This conditionally re-enables those through a `LINKERD2_PROXY_OUTBOUND_METRICS_HOSTNAME_LABELS` env var, wired through the policy/routing config with the option of individual policies and routes to set this separately from the global config.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-03-18 13:27:54 +00:00
dependabot[bot] 123d7a344e
build(deps): bump async-trait from 0.1.87 to 0.1.88 (#3764)
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.87 to 0.1.88.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.87...0.1.88)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 10:15:41 -04:00
dependabot[bot] 594f013902
build(deps): bump asn1-rs from 0.7.0 to 0.7.1 (#3765)
Bumps [asn1-rs](https://github.com/rusticata/asn1-rs) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/rusticata/asn1-rs/releases)
- [Changelog](https://github.com/rusticata/asn1-rs/blob/asn1-rs-0.7.1/CHANGELOG.md)
- [Commits](https://github.com/rusticata/asn1-rs/compare/asn1-rs-0.7.0...asn1-rs-0.7.1)

---
updated-dependencies:
- dependency-name: asn1-rs
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 10:15:17 -04:00
dependabot[bot] d7f961750f
build(deps): bump libc from 0.2.170 to 0.2.171 (#3766)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.170 to 0.2.171.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.171/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.170...0.2.171)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 10:14:38 -04:00
dependabot[bot] 2c2fc8b0d9
build(deps): bump uuid from 1.15.1 to 1.16.0 (#3767)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.15.1 to 1.16.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.15.1...v1.16.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 10:14:12 -04:00
dependabot[bot] e746454f50
build(deps): bump the rustls group across 1 directory with 4 updates (#3768)
Bumps the rustls group with 4 updates in the / directory: [tokio-rustls](https://github.com/rustls/tokio-rustls), [ring](https://github.com/briansmith/ring), [rustls-webpki](https://github.com/rustls/webpki) and [rustls](https://github.com/rustls/rustls).


Updates `tokio-rustls` from 0.26.1 to 0.26.2
- [Release notes](https://github.com/rustls/tokio-rustls/releases)
- [Commits](https://github.com/rustls/tokio-rustls/compare/v/0.26.1...v/0.26.2)

Updates `ring` from 0.17.13 to 0.17.14
- [Changelog](https://github.com/briansmith/ring/blob/main/RELEASES.md)
- [Commits](https://github.com/briansmith/ring/commits)

Updates `rustls-webpki` from 0.102.8 to 0.103.0
- [Release notes](https://github.com/rustls/webpki/releases)
- [Commits](https://github.com/rustls/webpki/compare/v/0.102.8...v/0.103.0)

Updates `rustls` from 0.23.23 to 0.23.24
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.23...v/0.23.24)

---
updated-dependencies:
- dependency-name: tokio-rustls
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rustls
- dependency-name: ring
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rustls
- dependency-name: rustls-webpki
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rustls
- dependency-name: rustls
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: rustls
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 10:13:48 -04:00
katelyn martin 23784c01a3
chore: use workspace-level package metadata (#3761)
this commit adds a `[workspace.package]` table at the root of the cargo
workspace. constituent manifests are updated to use the workspace-level
metadata.

this is generally a superficial chore, but has a pleasant future upside:
when new rust editions are released (e.g. 2024), we will only need to
update the edition specified at the root of the workspace.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-15 12:54:50 -04:00
dependabot[bot] c5215ad21e
build(deps): bump tj-actions/changed-files from 45.0.7 to 45.0.8 (#3760)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 45.0.7 to 45.0.8.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](dcc7a0cba8...9200e69727)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 11:50:48 -04:00
dependabot[bot] 2ab03e2b95
build(deps): bump tempfile from 3.17.1 to 3.19.0 (#3759)
* build(deps): bump tempfile from 3.17.1 to 3.19.0

Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.17.1 to 3.19.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.17.1...v3.19.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deny.toml): skip rustix v0.38

this commit adds mention of rustix, whose 1.0 release is still
propagating through the ecosystem, to the deny.toml.

nb: this also removes the bitflags directive, which no longer included a
duplicate version.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: katelyn martin <kate@buoyant.io>
2025-03-14 11:38:13 -04:00
dependabot[bot] 56faf968db
build(deps): bump once_cell from 1.21.0 to 1.21.1 (#3756)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.21.0 to 1.21.1.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.21.0...v1.21.1)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 11:31:41 -04:00
dependabot[bot] a616e96779
build(deps): bump aligned-vec from 0.6.1 to 0.6.2 (#3757)
Bumps [aligned-vec](https://github.com/sarah-ek/aligned-vec) from 0.6.1 to 0.6.2.
- [Commits](https://github.com/sarah-ek/aligned-vec/commits/v0.6.2)

---
updated-dependencies:
- dependency-name: aligned-vec
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 11:31:15 -04:00
dependabot[bot] 5a373bc569
build(deps): bump tokio-util from 0.7.13 to 0.7.14 (#3758)
Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.13 to 0.7.14.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.13...tokio-util-0.7.14)

---
updated-dependencies:
- dependency-name: tokio-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 11:30:08 -04:00
katelyn martin 11e990ee16
refactor(stack/loadshed): unit test instruments spawned tasks (#3755)
this commit performs a small refactor to one of the unit tests in
`linkerd-stack`'s load-shedding middleware.

this adds a span to the worker tasks spawned in this test, so that
tracing logs can be associated with particular oneshot services.

see #3744 for more information on upgrading our tower dependency. this
is cherry-picked from investigations on that branch related to breaking
changes in 0.5 related to the `Buffer` middleware.

after this change, logs now look like this:

```
; RUST_LOG="trace" cargo test -p linkerd-stack buffer_load_shed -- --nocapture

running 1 test
[     0.002770s] TRACE worker{id=oneshot1}: tower::buffer::service: sending request to buffer worker
[     0.002809s] TRACE worker{id=oneshot2}: tower::buffer::service: sending request to buffer worker
[     0.002823s] TRACE worker{id=oneshot3}: tower::buffer::service: sending request to buffer worker
[     0.002843s] DEBUG worker{id=oneshot4}: linkerd_stack::loadshed: Service has become unavailable
[     0.002851s] DEBUG worker{id=oneshot4}: linkerd_stack::loadshed: Service shedding load
[     0.002878s] TRACE tower::buffer::worker: worker polling for next message
[     0.002885s] TRACE tower::buffer::worker: processing new request
[     0.002892s] TRACE worker{id=oneshot1}: tower::buffer::worker: resumed=false worker received request; waiting for service readiness
[     0.002901s] DEBUG worker{id=oneshot1}: tower::buffer::worker: service.ready=true processing request
[     0.002914s] TRACE worker{id=oneshot1}: tower::buffer::worker: returning response future
[     0.002926s] TRACE tower::buffer::worker: worker polling for next message
[     0.002931s] TRACE tower::buffer::worker: processing new request
[     0.002935s] TRACE worker{id=oneshot2}: tower::buffer::worker: resumed=false worker received request; waiting for service readiness
[     0.002946s] TRACE worker{id=oneshot2}: tower::buffer::worker: service.ready=false delay
[     0.002983s] TRACE worker{id=oneshot5}: tower::buffer::service: sending request to buffer worker
[     0.003001s] DEBUG worker{id=oneshot6}: linkerd_stack::loadshed: Service has become unavailable
[     0.003007s] DEBUG worker{id=oneshot6}: linkerd_stack::loadshed: Service shedding load
[     0.003017s] DEBUG worker{id=oneshot7}: linkerd_stack::loadshed: Service has become unavailable
[     0.003024s] DEBUG worker{id=oneshot7}: linkerd_stack::loadshed: Service shedding load
[     0.003035s] TRACE tower::buffer::worker: worker polling for next message
[     0.003041s] TRACE tower::buffer::worker: resuming buffered request
[     0.003045s] TRACE worker{id=oneshot2}: tower::buffer::worker: resumed=true worker received request; waiting for service readiness
[     0.003052s] DEBUG worker{id=oneshot2}: tower::buffer::worker: service.ready=true processing request
[     0.003060s] TRACE worker{id=oneshot2}: tower::buffer::worker: returning response future
[     0.003068s] TRACE tower::buffer::worker: worker polling for next message
[     0.003073s] TRACE tower::buffer::worker: processing new request
[     0.003077s] TRACE worker{id=oneshot3}: tower::buffer::worker: resumed=false worker received request; waiting for service readiness
[     0.003084s] DEBUG worker{id=oneshot3}: tower::buffer::worker: service.ready=true processing request
[     0.003091s] TRACE worker{id=oneshot3}: tower::buffer::worker: returning response future
[     0.003099s] TRACE tower::buffer::worker: worker polling for next message
[     0.003103s] TRACE tower::buffer::worker: processing new request
[     0.003107s] TRACE worker{id=oneshot5}: tower::buffer::worker: resumed=false worker received request; waiting for service readiness
[     0.003114s] DEBUG worker{id=oneshot5}: tower::buffer::worker: service.ready=true processing request
[     0.003121s] TRACE worker{id=oneshot5}: tower::buffer::worker: returning response future
[     0.003129s] TRACE tower::buffer::worker: worker polling for next message
test loadshed::tests::buffer_load_shed ... ok
```

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-13 13:26:21 -04:00
dependabot[bot] 5fa3745b57
build(deps): bump resolv-conf from 0.7.0 to 0.7.1 (#3751)
Bumps [resolv-conf](https://github.com/hickory-dns/resolv-conf) from 0.7.0 to 0.7.1.
- [Commits](https://github.com/hickory-dns/resolv-conf/commits)

---
updated-dependencies:
- dependency-name: resolv-conf
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 09:43:41 -04:00
dependabot[bot] e67ac67288
build(deps): bump http from 0.2.11 to 0.2.12 (#3754)
Bumps [http](https://github.com/hyperium/http) from 0.2.11 to 0.2.12.
- [Release notes](https://github.com/hyperium/http/releases)
- [Changelog](https://github.com/hyperium/http/blob/v0.2.12/CHANGELOG.md)
- [Commits](https://github.com/hyperium/http/compare/v0.2.11...v0.2.12)

---
updated-dependencies:
- dependency-name: http
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 09:42:47 -04:00
dependabot[bot] a8390b2ee6
build(deps): bump syn from 2.0.99 to 2.0.100 (#3752)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.99 to 2.0.100.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.99...2.0.100)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 09:42:08 -04:00
katelyn martin c35cf270cf
chore(deps): address RUSTSEC-2025-0014 (#3750)
this commit replaces `humantime`, which is no longer maintained, with
`jiff`.

see this error when `main` today is built:

```
error[unmaintained]: humantime is unmaintained
   ┌─ /linkerd/linkerd2-proxy/Cargo.lock:78:1
   │
78 │ humantime 2.1.0 registry+https://github.com/rust-lang/crates.io-index
   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unmaintained advisory detected
   │
   ├ ID: RUSTSEC-2025-0014
   ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2025-0014
   ├ Latest `humantime` crates.io release is four years old and GitHub repository has
     not seen commits in four years. Question about maintenance status has not gotten
     any reaction from maintainer: https://github.com/tailhook/humantime/issues/31

     ## Possible alternatives

      * [jiff](https://crates.io/crates/jiff) provides same kind of functionality
   ├ Announcement: https://github.com/tailhook/humantime/issues/31
   ├ Solution: No safe upgrade is available!
   ├ humantime v2.1.0
     └── linkerd-http-access-log v0.1.0
         └── linkerd-app-inbound v0.1.0
             ├── linkerd-app v0.1.0
             │   ├── linkerd-app-integration v0.1.0
             │   └── linkerd2-proxy v0.1.0
             ├── linkerd-app-admin v0.1.0
             │   ├── linkerd-app v0.1.0 (*)
             │   └── (dev) linkerd-app-integration v0.1.0 (*)
             └── linkerd-app-gateway v0.1.0
                 └── linkerd-app v0.1.0 (*)

advisories FAILED, bans ok, licenses ok, sources ok
```

see:
  * https://github.com/rustsec/advisory-db/pull/2249.
  * https://github.com/tailhook/humantime/issues/31.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-12 16:05:03 -07:00
dependabot[bot] d3b4ad6362
build(deps): bump dtoa from 1.0.9 to 1.0.10 (#3749)
Bumps [dtoa](https://github.com/dtolnay/dtoa) from 1.0.9 to 1.0.10.
- [Release notes](https://github.com/dtolnay/dtoa/releases)
- [Commits](https://github.com/dtolnay/dtoa/compare/1.0.9...1.0.10)

---
updated-dependencies:
- dependency-name: dtoa
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 09:58:59 -04:00
dependabot[bot] 332e29af5c
build(deps): bump prettyplease from 0.2.29 to 0.2.30 (#3747)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.29 to 0.2.30.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.29...0.2.30)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 09:58:28 -04:00
dependabot[bot] 6d7b165727
build(deps): bump once_cell from 1.20.3 to 1.21.0 (#3748)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.20.3 to 1.21.0.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.3...v1.21.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 09:58:02 -04:00
dependabot[bot] df651278f2
build(deps): bump quote from 1.0.39 to 1.0.40 (#3746)
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.39 to 1.0.40.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.39...1.0.40)

---
updated-dependencies:
- dependency-name: quote
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 09:57:24 -04:00
Oliver Gould 16b2ff7232
chore(cargo): make prometheus-client a workspace dependency (#3743) 2025-03-11 22:38:39 +00:00
Oliver Gould 46babf0849
chore(metrics): use kubert-prometheus-process metrics (#3742)
kubert-prometheus-process is a new crate that includes all of Linkerd's system
metrics and more. This also helps avoid annoying compilation build issues on
non-Linux systems.
2025-03-11 18:37:17 -04:00
katelyn martin 575ba0008b
chore(deps): use `prometheus-client` v0.23 (#3732)
this updates the prometheus client dependency.

additionally, this commit updates the `kubert-prometheus-tokio`
dependency, so that we agree on the client library in use.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-11 21:42:13 +00:00
Oliver Gould 4c79bdf730
chore(metrics): clean up feature flagging (#3741)
linkerd-metrics exposes a 'stack' feature but uses a 'linkerd-stack' feature
internally. This change cleans this up.
2025-03-11 15:46:39 -04:00
Oliver Gould 87d6d38510
chore(app-core): remove unused linkerd-system dep (#3740) 2025-03-11 19:43:27 +00:00
Oliver Gould ed42c2ad3a
feat(runtime): support CORES_MIN, CORES_MAX, and CORES_MAX_RATIO (#3731)
When the proxy boots up, it needs to select a number of I/O worker threads to
allocate to the runtime. This change adds a new environment variable that allows
this value to scale based on the number of CPUs available on on the host.

A CORES_MAX_RATIO value of 1.0 will allocate one worker thread per CPU core. A
lesser value will allocate fewer worker threads. Values are rounded to the
nearest whole number.

The CORES_MIN value sets a lower bound on the number of worker threads to use.
The CORES_MAX value sets an upper bound.
2025-03-11 18:53:30 +00:00
katelyn martin 13a79167d7
refactor(stack/switch_ready): use `Either<A, B>` future (#3739)
this commit makes a noöp change to the `SwitchReady<A, B>` machinery
provided by our `linkerd-stack` library.

this commit is a small refactor that is intended to pave the way for an
impending upgrade to tower v0.5, which notably includes breaking changes
to the `tower::util::Either<A, B>` service.

as of tower v0.5, by way of https://github.com/tower-rs/tower/pull/637,
the `Either<A, B>` service is no longer itself a `Future`. so, we can
instead use the future provided by `futures`.

for more information, see:
* https://github.com/linkerd/linkerd2/issues/8733
* https://github.com/linkerd/linkerd2-proxy/pull/3504
* https://github.com/linkerd/linkerd2-proxy/pull/3504/files#r1988082658
* https://github.com/tower-rs/tower/pull/637

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-11 14:50:51 -04:00
Oliver Gould 1c15dd087d
chore(linkerd2-proxy): always enable multicore features (#3738)
The proxy predates the multi-threaded tokio runtime. When switching to it, we
added a 'multicore' feature to adopt it incrementally. This has been the only
supported configuration for many years now.

This change removes the needless feature flag to simplify the runtime
configuration.
2025-03-11 17:08:26 +00:00
Oliver Gould a683ff5c67
feat(outbound): instrument per-parent connection protocol counts (#3733)
The outbound proxy makes protocol decisions based on the discovery response,
keyed on a "parent" reference.

This change adds a `protocol::metrics` middleware that records connection counts
by parent reference.
2025-03-11 09:49:45 -07:00
dependabot[bot] ec168c3977
build(deps): bump tinyvec from 1.8.1 to 1.9.0 (#3737)
Bumps [tinyvec](https://github.com/Lokathor/tinyvec) from 1.8.1 to 1.9.0.
- [Changelog](https://github.com/Lokathor/tinyvec/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Lokathor/tinyvec/compare/v1.8.1...v1.9.0)

---
updated-dependencies:
- dependency-name: tinyvec
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-11 07:18:58 -07:00
dependabot[bot] 0dc3c8dde4
build(deps): bump indexmap from 2.7.1 to 2.8.0 (#3736)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.7.1 to 2.8.0.
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.7.1...2.8.0)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-11 07:18:47 -07:00
dependabot[bot] f2bc4cd76d
build(deps): bump bytes from 1.10.0 to 1.10.1 (#3735)
Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.10.0 to 1.10.1.
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.10.0...v1.10.1)

---
updated-dependencies:
- dependency-name: bytes
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-11 07:18:36 -07:00
dependabot[bot] 72ee0b31d2
build(deps): bump quote from 1.0.38 to 1.0.39 (#3734)
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.38 to 1.0.39.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.38...1.0.39)

---
updated-dependencies:
- dependency-name: quote
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-11 07:18:23 -07:00
Oliver Gould 64c608ca8d
feat(inbound): record metrics about transport header usage (#3723)
Inbound proxies may receive meshed traffic directly on the proxy's inbound port
with a transport header, informing inbound routing behavior.

This change updates the inbound proxy to record metrics about the usage of
transport headers, including the total number of requests with a transport
header by session protocol and target port.
2025-03-10 14:07:38 -07:00
Oliver Gould 25bc9730ee
feat: instrument HTTP protocol detection metrics (#3722)
This change updates the DetectHttp middleware to record metrics about HTTP
protocol detection. Specfically, it records the the counts of results and a very
coarse histogram of the time taken to detect the protocol.

The inbound, outbound, and admin (via inbound) stacks are updated to record
metrics against the main registry.
2025-03-10 11:12:56 -07:00
Oliver Gould e7c2afd5c1
feat(http/detect)!: error when the socket is closed (#3721)
* refactor(http): consolidate HTTP protocol detection

Linkerd's HTTP protocol detection logic is spread across a few crates: the
linkerd-detect crate is generic over the actual protocol detection logic, and
the linkerd-proxy-http crate provides an implementation. There are no other
implemetations of the Detect interface. This leads to gnarly type signatures in
the form `Result<Option<http::Variant>, DetectTimeoutError>`: simultaneously
verbose and not particularly informative (what does the None case mean exactly).

This commit introduces a new crate, `linkerd-http-detect`, consolidating this
logic and removes the prior implementations. The admin, inbound, and outbound
stacks are updated to use these new types. This work is done in anticipation of
introducing metrics that report HTTP detection behavior.

There are no functional changes.

* feat(http/detect)!: error when the socket is closed

When a proxy does protocol detection, the initial read may indicate that the
connection was closed by the client with no data being written to the socket. In
such a case, the proxy continues to process the connection as if may be proxied,
but we expect this to fail immediately. This can lead to unexpected proxy
behavior: for example, inbound proxies may report policy denials.

To address this, this change surfaces an error (as if the read call failed).
This could, theoretically, impact some bizarre clients that initiate half-open
connections. These corner cases can use explicit opaque policies to bypass
detection.
2025-03-10 08:31:17 -07:00
dependabot[bot] 606b51ba32
build(deps): bump thiserror from 2.0.11 to 2.0.12 (#3728)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.11 to 2.0.12.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.11...2.0.12)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 08:02:20 -07:00
dependabot[bot] 3a7d207950
build(deps): bump ryu from 1.0.19 to 1.0.20 (#3729)
Bumps [ryu](https://github.com/dtolnay/ryu) from 1.0.19 to 1.0.20.
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.19...1.0.20)

---
updated-dependencies:
- dependency-name: ryu
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 08:01:36 -07:00
dependabot[bot] 77b21876cd
build(deps): bump serde from 1.0.218 to 1.0.219 (#3727)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.218 to 1.0.219.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.218...v1.0.219)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 08:01:20 -07:00
dependabot[bot] 5a0fe3d221
build(deps): bump time from 0.3.37 to 0.3.39 (#3726)
Bumps [time](https://github.com/time-rs/time) from 0.3.37 to 0.3.39.
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.37...v0.3.39)

---
updated-dependencies:
- dependency-name: time
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 08:01:02 -07:00
Oliver Gould fc928b637a
feat(inbound): include srv_port label in server metrics (#3725)
We include a group/version/kind for inbound server resources, but we do not
indicate which specific port the server is applied to. This is important context
to understand the inbound proxy's behavior, especially when using the default
servers.

This change adds a `srv_port` label to inbound server metrics to definitively
and consistently indicate the server port used for inbound policy.
2025-03-09 20:40:22 -04:00
Oliver Gould 9f5a6cce27
fix(inbound): correct error message when transport header is missing (#3724)
The RefusedNoTarget error type is a remnant of an older version of the direct
stack. This commit updates the error message to reflect the current state of the
code: we require ALPN-negotiated transport headers on all direct connections.
2025-03-09 19:46:45 -04:00
Oliver Gould c87d202098
refactor(http): consolidate HTTP protocol detection (#3720)
Linkerd's HTTP protocol detection logic is spread across a few crates: the
linkerd-detect crate is generic over the actual protocol detection logic, and
the linkerd-proxy-http crate provides an implementation. There are no other
implemetations of the Detect interface. This leads to gnarly type signatures in
the form `Result<Option<http::Variant>, DetectTimeoutError>`: simultaneously
verbose and not particularly informative (what does the None case mean exactly).

This commit introduces a new crate, `linkerd-http-detect`, consolidating this
logic and removes the prior implementations. The admin, inbound, and outbound
stacks are updated to use these new types. This work is done in anticipation of
introducing metrics that report HTTP detection behavior.

There are no functional changes.
2025-03-09 08:27:25 -07:00
Oliver Gould 114ee8d878
fix(just): make dev versions semver (#3719)
Our build can occaisionally fail when the sha is not a valid semver label:

    --- stdout
    cargo:rustc-env=GIT_SHA=025979070
    cargo:rustc-env=LINKERD2_PROXY_BUILD_DATE=2025-03-08T16:32:34Z
    --- stderr
    thread 'main' panicked at linkerd/app/core/build.rs:18:17:
    LINKERD2_PROXY_VERSION must be semver: version='0.0.0-dev.025979070'
       error='invalid leading zero in pre-release identifier'

To fix this, the dot is removed so the version string is 0.0.0-dev025979070,
which is valid.
2025-03-08 18:30:06 -05:00
katelyn martin 4f24b84ee0
chore(deps): `tower` is a workspace dependency (#3718)
pr #3715 missed a small handful of cargo dependencies. this commit marks
these so that they also use the workspace-level tower version.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-08 10:17:51 -08:00
katelyn martin 09ecbd79b7
chore(deps): `drain` is a workspace dependency (#3717)
see https://github.com/linkerd/linkerd2/issues/8733 and
https://github.com/linkerd/linkerd2-proxy/pull/3504 for more
information.

see also linkerd/drain-rs#36 for a related pull request that
updated `drain`'s `tower` dependency. see #3715 (2f97549a) for a related
pull request that made `tower` a workspace dependency.

see #3456 (c740b6d8), #3466 (ca50d6bb), #3473 (b87455a9), and #3701
(cf4ef39), for some other previous pr's that moved dependencies to be
managed at the workspace level.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-07 16:34:24 -05:00
katelyn martin 4589be41ee
nit(detect): sort dependencies (#3716)
this is a follow-on to #3715.

this commit sorts the dependencies in this manifest.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-07 13:05:13 -08:00
katelyn martin 2f97549aed
chore(deps): `tower` crates are workspace dependencies (#3715)
* chore(deps): `tower` is a workspace dependency

see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

see https://github.com/linkerd/linkerd2-proxy/pull/3504 as well.

see #3456 (c740b6d8), #3466 (ca50d6bb), #3473 (b87455a9), and #3701
(cf4ef39) for some other previous pr's that moved dependencies to be
managed at the workspace level.

see also https://github.com/linkerd/drain-rs/pull/36 for another related
pull request that relates to our tower dependency.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(deps): `tower-service` is a workspace dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(deps): `tower-test` is a workspace dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-07 14:58:18 -05:00
katelyn martin d2111e59b9
chore(deps): update to ring 0.17.13 (#3713)
https://rustsec.org/advisories/RUSTSEC-2025-0009.html

0.17.11 is vulnerable to RUSTSEC-2025-0009. this commit updates the
`ring` dependency to a patched version.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-07 12:19:13 -05:00
dependabot[bot] 4a2bf8d876
build(deps): bump rustversion from 1.0.19 to 1.0.20 (#3712)
Bumps [rustversion](https://github.com/dtolnay/rustversion) from 1.0.19 to 1.0.20.
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.19...1.0.20)

---
updated-dependencies:
- dependency-name: rustversion
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-07 07:28:18 -08:00
dependabot[bot] bba79fd1dd
build(deps): bump either from 1.14.0 to 1.15.0 (#3711)
Bumps [either](https://github.com/rayon-rs/either) from 1.14.0 to 1.15.0.
- [Commits](https://github.com/rayon-rs/either/compare/1.14.0...1.15.0)

---
updated-dependencies:
- dependency-name: either
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-07 07:28:04 -08:00
dependabot[bot] c6c369c41f
build(deps): bump semver from 1.0.25 to 1.0.26 (#3710)
Bumps [semver](https://github.com/dtolnay/semver) from 1.0.25 to 1.0.26.
- [Commits](https://github.com/dtolnay/semver/compare/1.0.25...1.0.26)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-07 07:27:52 -08:00
dependabot[bot] a1d49e9ee8
build(deps): bump unicode-ident from 1.0.17 to 1.0.18 (#3709)
Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.17 to 1.0.18.
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.17...1.0.18)

---
updated-dependencies:
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-07 07:27:39 -08:00
katelyn martin 90e005a832
chore(deps): remove unused `opencensus`, `opentelemetry` dependencies (#3708)
noticed while addressing `cargo-deny` errors in #3504. these crates
include a few unused dependencies, which we can remove. while we
are in the neighborhood, we make some subjective tweaks to tidy up
these imports.

---

* chore(opentelemetry): remove unused `http` dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(opentelemetry): tidy imports

this groups imports at the crate level, and directly imports some
imports from their respective crates rather than through an alias of
said crate. a `self` prefix is added to clarify imports from submodules
of this crate.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(opentelemetry): remove unused `tokio-stream` dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(opencensus): remove unused `http` dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(opencensus): use self prefix in import

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-06 14:03:16 -08:00
Scott Fleener 40a622ee48
fix(inbound): instrument http connections in tagged transport stack (#3707)
Currently, TCP metrics are not logged for HTTP requests coming in through the tagged transport header stack.

This adds that instrumentation, like we do for the opaque and gateway stacks already present.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-03-06 20:19:30 +00:00
katelyn martin cf4ef39a89
chore(deps): `prost-build` is a workspace dependency (#3701)
see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

this commit moves `prost-build` so that it is now managed as a workspace
dependency. while only used in tests, these tests can fail if this is
not versioned in lockstep with our other protobuffer dependencies.

see #3456 (c740b6d8), #3466 (ca50d6bb), and especially #3473 (b87455a9)
for some other previous pr's that moved dependencies to be managed at
the workspace level.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-06 08:24:19 -08:00
dependabot[bot] cd34762962
build(deps): bump serde_json from 1.0.139 to 1.0.140 (#3706)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.139 to 1.0.140.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.139...v1.0.140)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-06 05:48:14 -05:00
dependabot[bot] d98cff0b74
build(deps): bump pin-project from 1.1.9 to 1.1.10 (#3705)
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 1.1.9 to 1.1.10.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v1.1.9...v1.1.10)

---
updated-dependencies:
- dependency-name: pin-project
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-06 05:47:41 -05:00
dependabot[bot] 0b4420ec6a
build(deps): bump symbolic-demangle from 12.13.4 to 12.14.1 (#3704)
Bumps [symbolic-demangle](https://github.com/getsentry/symbolic) from 12.13.4 to 12.14.1.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.13.4...12.14.1)

---
updated-dependencies:
- dependency-name: symbolic-demangle
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-06 05:46:53 -05:00
dependabot[bot] f1c8eb0487
build(deps): bump httparse from 1.10.0 to 1.10.1 (#3703)
Bumps [httparse](https://github.com/seanmonstar/httparse) from 1.10.0 to 1.10.1.
- [Release notes](https://github.com/seanmonstar/httparse/releases)
- [Commits](https://github.com/seanmonstar/httparse/compare/v1.10.0...v1.10.1)

---
updated-dependencies:
- dependency-name: httparse
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-06 05:46:10 -05:00
katelyn martin f5b4f6b1c6
refactor(app/integration): remove artificial `Sync` bounds (#3700)
see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

we are in the process of upgrading to hyper 1.x.

in the process of doing so, we will wish to use our friendly `BoxBody`
type, which provides a convenient and reusable interface to abstract
over different artitrary `B`-typed request and response bodies.

unfortunately, by virtue of its definition, it is not a `Sync` type:

```rust
 pub struct BoxBody {
     inner: Pin<Box<dyn Body<Data = Data, Error = Error> + Send + 'static>>,
 }

 #[pin_project]
 pub struct Data {
     #[pin]
     inner: Box<dyn bytes::Buf + Send + 'static>,
 }
```

these are erased `Box<dyn ..>` objects that only ensure `Send`-ness.

rather than changing that, because that is the proper definition of the
type, we should update code in our test client and test server to stop
requesting arbitrary `Sync` bounds.

this commit removes `Sync` bounds from various places that in fact only
need be `Send + 'static`.

this will help facilitate making use of `BoxBody` in #3504.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-04 15:29:03 -08:00
katelyn martin dacf85896e
refactor(app/integration): forward-compatible test code (#3699)
see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

see https://github.com/linkerd/linkerd2-proxy/pull/3559 and
https://github.com/linkerd/linkerd2-proxy/pull/3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

`telemetry::log_stream::collect_logs` is a function responsible for
digesting a streaming body, and deserializing each chunk into a
`serde_json::Value`, until either (a) a shutdown signal is received, or
(b) the end of the body is reached.

this commit updates test code in `linkerd-app-integration` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
https://github.com/linkerd/linkerd2-proxy/pull/3504, which will only
need to remove this adapter once using hyper 1.0.

* https://github.com/linkerd/linkerd2/issues/8733
* https://github.com/linkerd/linkerd2-proxy/pull/3671
* https://github.com/linkerd/linkerd2-proxy/pull/3672
* https://github.com/linkerd/linkerd2-proxy/pull/3673
* https://github.com/linkerd/linkerd2-proxy/pull/3676

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-04 11:37:58 -08:00
katelyn martin d4bfd607c5
refactor(app/integration): remove unused `TcpConn::target_addr()` (#3695)
this method is not used by any test code, nor any other internal code.

this commit removes
`linkerd_app_integration::tcp::TcpConn::target_addr()`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-04 10:06:11 -08:00
katelyn martin 16614ca2d5
refactor(app/integration): remove unused `request_init_method()` (#3698)
`TapEventExt` provides an extension trait interface that we use to
extends `linkerd_proxy_api::tap::TapEvent` with additional interfaces
for use in integration tests.

this commit removes `request_init_path()`. this method was originally
added in 3ac6b72c4 (#154), but was never actually implemented and will
only ever panic when invoked. thus, it can be removed.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-04 16:03:53 +00:00
katelyn martin 8117c51a4a
nit(app/integration): tidy `tcp` imports (#3696)
we follow a convention of grouping imported symbols at the crate-level.

this commit tidies up imports in `linkerd_app_integration::tcp` to
follow this convention.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-04 07:59:24 -08:00
katelyn martin 799583af90
refactor(app/integration): call `tcp::client()` directly (#3694)
`linkerd_app_integration::tcp` provides a `TcpClient` type that is
distinct from the primary `linkerd_app_integration::client::Client` type
broadly used in integration tests.

this commit makes a small change to reduce indirection, and clarify that
this is constructing a different client implementation from a different
submodule.

this removes `linkerd_app_integration::client::tcp()`, and updates test
code to call the `tcp::client()` function that this is masking.

this is the client-side equivalent to #3688 (a10d1d7e).

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-04 07:59:13 -08:00
katelyn martin 4e3119cd45
refactor(app/integration): clean up `Server` constructors (#3693)
this commit removes some misdirection from the various constructors for
our test server.

currently, we expose a family of constructor functions `server::new()`,
`server::http1()`, ..., and so forth.

each of these invoke a private `server::Server::http1()`,
`server::Server::http2()`, `server::Server::http2_tls()`, ...,
counterpart, which then delegates down once more to another private
constructor `server::Server::new()`.

this is all a bit roundabout, particularly because these private
constructors are not used by any other internal code in the `server`
submodule.

this commit removes these inherent `Server` constructors, since they are
private and not used by any test code. each free-standing constructor
function is altered to instead directly construct a `Server`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-04 00:42:01 +00:00
katelyn martin ce7e6645e3
refactor(app/integration): remove `Request`, `Response` aliases (#3692)
* refactor(app/integration): remove `Request`, `Response` aliases

see https://github.com/linkerd/linkerd2/issues/8733.

this commit removes two type aliases from our test server
implementation. these are each tied to the defunct `hyper::Body` type.

since much of this code was originally written (between 2017 and 2020)
we've since developed some patterns / idioms elsewhere for dealing with
request and response bodies.

to help set the stage for tweaks to which interfaces need
`hyper::body::Incoming`, which types work with our general default of
`BoxBody`, and which can be generic across arbitrary `B`-typed bodies,
we remove these aliases and provide the body parameter to `Request` and
`Response`.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/integration): remove `Request`, `Response` aliases

see https://github.com/linkerd/linkerd2/issues/8733.

this commit removes two type aliases from our test client
implementation. these are each tied to the defunct `hyper::Body` type.

since much of this code was originally written (between 2017 and 2020)
we've since developed some patterns / idioms elsewhere for dealing with
request and response bodies.

to help set the stage for tweaks to which interfaces need
`hyper::body::Incoming`, which types work with our general default of
`BoxBody`, and which can be generic across arbitrary `B`-typed bodies,
we remove these aliases and provide the body parameter to `Request` and
`Response`.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 23:46:09 +00:00
katelyn martin 84c3b8491e
nit(app/integration): add/remove whitespace for consistency (#3689)
* nit(app/integration): add whitespace for consistency

we follow a convention of an empty line between functions.

this commit adds an empty line.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(app/integration): remove whitespace for consistency

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(app/integration): add whitespace for consistency

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 18:39:55 -05:00
katelyn martin abc8364f39
nit(app/integration): use `OK`, `NOT_FOUND` constants (#3691)
these constants exist, and are generally considered a best practice for
these situations.

this commit replaces numeric literals with named constants.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 18:39:03 -05:00
katelyn martin f4eac760f0
refactor(app/integration): use `linker_app_core::Error` (#3690)
the test server implementation in `linkerd_app_integration` defines an
`BoxError` alias. we have a boxed error type in
`linkerd_app_core::Error` that achieves the same purpose, that we can
use instead.

this commit replaces this type alias with a reëxport of
`linkerd_app_core::Error`.

see also, #3685, which removed another similar alias.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 18:38:48 -05:00
katelyn martin a10d1d7ef8
refactor(app/integration): call `tcp::server()` directly (#3688)
`linkerd_app_integration::tcp` provides a `TcpServer` type that is
distinct from the primary `linkerd_app_integration::server::Server` type
broadly used in integration tests.

this commit makes a small change to reduce indirection, and clarify that
this is constructing a different server implementation from a
different submodule.

this removes `linkerd_app_integration::server::tcp()`, and updates test
code to call the `tcp::server()` function that this is masking.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 16:20:45 -05:00
katelyn martin cd3a200a5e
refactor(app/integration): remove inert `NewService<T>` (#3687)
elsewhere in our codebase, we follow a pattern that can be called a
"new service". this is a `Service<T>` whose response `S` is itself
a `Service<U>`.

new services are often useful for dealing with particular connection
semantics, and provide us a way to model a connection that services many
requests.

our test server code makes use of a `Svc`, which wraps a reference to a
map of uri's and routes. there is an associated `NewSvc` type that does
not provide any material benefit. this `NewSvc` type is a `Service<()>`
that never exerts backpressure, nor performs any action besides
`Arc::clone`ing the map of routes.

this commit golfs down `linkerd_app_integration::server::Server`, by
directly cloning the routes into a `Svc(_)`, without the need for
polling a future or handling an (impossible) error.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 16:20:29 -05:00
katelyn martin be868306f5
refactor(app/integration): inline `Running` future (#3686)
`linkerd_app_integration::running()` is a public function that is not
used by any external callers. this function is used in one place, when
setting up test client used for integration tests.

this commit inlines this logic, and moves the associated `Running` type
alias down alongside the `Run` enum.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 14:22:16 -05:00
Oliver Gould 93aecec642
chore(just): add windows os target (#3683)
To support cross-compilation to windows, this change adds an 'os' param to the
justfile, used in the release to cross-build to x86_64-pc-windows-gnu.

This will produce a binary named 'linkerd2-proxy-v2.999.9-x86_64.exe'.

The proxy does not yet compile on windows, so this is a placeholder for now.
2025-03-03 19:07:05 +00:00
katelyn martin 7aa7f069ea
refactor(app/integration): use `linkerd_app_core::Error` (#3685)
`linkerd_app_integration` defines an `Error` alias.

we have a boxed error type in `linkerd_app_core::Error` that achieves
the same purpose, that we can use instead.

this commit replaces this type alias with a reëxport of
`linkerd_app_core::Error`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 14:05:34 -05:00
Oliver Gould 3afd59cac2
fix(ci): remove EmbarkStudios/cargo-deny-action (#3684)
cargo-deny-action is broken: EmbarkStudios/cargo-deny-action#91

This change replaces the action with a manual invocation.
2025-03-03 17:57:56 +00:00
katelyn martin 672727effa
refactor(app/integration): clarify `<SyncSvc as Service<T>>::call()` (#3677)
* refactor(app/integration): use `Result::expect()`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/integration): clarify `<SyncSvc as Service<T>>::call()`

this commit makes some cosmetic changes to
`linkerd_app_integration::tap::SyncSvc`'s implementation of
`tower::Service<T>`.

documentation comments are added to clarify something that makes this
service slightly interesting, and notably different from code suitable
for use in production / real-world contexts.

this service wraps an underlying `Client`, and provides a service
implementation that deals with arbitrary `B`-typed request bodies.
this provides a flexible adapter that simplifies test code.

this service, however, *blocks* the calling thread (off-task) to collect
the body into a cheaply-cloneable `Bytes`.

this commit outlines that logic into an associated function and adds
additional documentation noting this property, and the basis for this
assumption.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/integration): loosen `SyncSvc` bounds

the bounds placed upon the inbound request's `B`-typed body are overly
restrictive for `<SyncSvc as Service<T>>`. this commit removes some
superfluous bounds, so that only those that are currently needed by this
code are now required.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-03-03 10:57:49 -05:00
dependabot[bot] 7e52a0acc6
build(deps): bump syn from 2.0.98 to 2.0.99 (#3679)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.98 to 2.0.99.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.98...2.0.99)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 09:04:56 -05:00
dependabot[bot] ae60a095bb
build(deps): bump async-trait from 0.1.86 to 0.1.87 (#3680)
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.86 to 0.1.87.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.86...0.1.87)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 09:04:49 -05:00
dependabot[bot] b230f7b792
build(deps): bump proc-macro2 from 1.0.93 to 1.0.94 (#3681)
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.93 to 1.0.94.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.93...1.0.94)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 09:04:41 -05:00
dependabot[bot] 7038e314bb
build(deps): bump anyhow from 1.0.96 to 1.0.97 (#3682)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.96 to 1.0.97.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.96...1.0.97)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 09:04:33 -05:00
katelyn martin 6b4ca820c7
refactor(app/outbound): forward-compatible test code (#3676)
see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

see https://github.com/linkerd/linkerd2-proxy/pull/3559 and
https://github.com/linkerd/linkerd2-proxy/pull/3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-outbound` related to
timeouts so that it interacts with request and response bodies via an
adapter that polls for frames in a manner consistent with the 1.0 api of
`http_body`.

this allows us to limit the diff in
https://github.com/linkerd/linkerd2-proxy/pull/3504, which will only
need to remove this adapter once using hyper 1.0.

see #3671, #3672, and #3673, which performed the same change for
`linkerd-app-inbound`, other code in `linkerd-app-outbound`, and
`linkerd-app-integration`, respectively.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-28 11:01:44 -05:00
katelyn martin 67b4d419cf
refactor(app/integration): forward-compatible test code (#3673)
see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

see https://github.com/linkerd/linkerd2-proxy/pull/3559 and
https://github.com/linkerd/linkerd2-proxy/pull/3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-integration` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
https://github.com/linkerd/linkerd2-proxy/pull/3504, which will only
need to remove this adapter once using hyper 1.0.

see #3671 and #3672, which perform the same change for
`linkerd-app-inbound` and `linkerd-app-outbound`, respectively.

---

* chore(app/integration): `linkerd-http-body-compat` test dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/integration): generalize `hyper::Body`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/integration): use `ForwardCompatibleBody`

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-28 09:34:03 -05:00
katelyn martin f934c8040b
refactor(app/outbound): forward-compatible test code (#3672)
see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

see https://github.com/linkerd/linkerd2-proxy/pull/3559 and
https://github.com/linkerd/linkerd2-proxy/pull/3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-outbound` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
https://github.com/linkerd/linkerd2-proxy/pull/3504, which will only
need to remove this adapter once using hyper 1.0.

see #3671 and #3673, which perform the same change for
`linkerd-app-inbound` and `linkerd-app-integration`, respectively.

---

* chore(app/outbound): `linkerd-http-body-compat` test dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/outbound): use `Response::into_body()`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/outbound): use `ForwardCompatibleBody`

see https://github.com/linkerd/linkerd2/issues/8733.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/outbound): use `ForwardCompatibleBody`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/outbound): use `ForwardCompatibleBody`

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/outbound): use `ForwardCompatibleBody`

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-28 09:33:55 -05:00
katelyn martin d02c377222
refactor(app/inbound): forward-compatible test code (#3671)
see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

see https://github.com/linkerd/linkerd2-proxy/pull/3559 and
https://github.com/linkerd/linkerd2-proxy/pull/3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-inbound` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
https://github.com/linkerd/linkerd2-proxy/pull/3504, which will only
need to remove this adapter once using hyper 1.0.

see #3672 and #3673, which perform the same change for
`linkerd-app-outbound` and `linkerd-app-integration`, respectively.

---

* refactor(app/inbound): `linkerd-http-body-compat` test dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/inbound): use `ForwardCompatibleBody`

see https://github.com/linkerd/linkerd2/issues/8733.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-28 09:33:48 -05:00
dependabot[bot] ecbc3ec1fe
build(deps): bump cc from 1.2.15 to 1.2.16 (#3675)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.15 to 1.2.16.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.15...cc-v1.2.16)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 05:24:45 -08:00
dependabot[bot] 2584fcd9a0
build(deps): bump the boring group with 2 updates (#3667)
Bumps the boring group with 2 updates: [boring](https://github.com/cloudflare/boring) and [boring-sys](https://github.com/cloudflare/boring).


Updates `boring` from 4.14.0 to 4.15.0
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.14.0...v4.15.0)

Updates `boring-sys` from 4.14.0 to 4.15.0
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.14.0...v4.15.0)

---
updated-dependencies:
- dependency-name: boring
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: boring
- dependency-name: boring-sys
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: boring
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 13:34:13 -05:00
dependabot[bot] d4ab1b774c
build(deps): bump the tracing group with 2 updates (#3669)
Bumps the tracing group with 2 updates: [tracing-subscriber](https://github.com/tokio-rs/tracing) and [tracing-serde](https://github.com/tokio-rs/tracing).


Updates `tracing-subscriber` from 0.3.18 to 0.3.19
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.18...tracing-subscriber-0.3.19)

Updates `tracing-serde` from 0.1.3 to 0.2.0
- [Release notes](https://github.com/tokio-rs/tracing/releases)
- [Commits](https://github.com/tokio-rs/tracing/compare/tracing-serde-0.1.3...tracing-serde-0.2.0)

---
updated-dependencies:
- dependency-name: tracing-subscriber
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: tracing
- dependency-name: tracing-serde
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: tracing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 13:34:04 -05:00
dependabot[bot] a92a3871cd
build(deps): bump tokio-boring from 4.14.0 to 4.15.0 (#3670)
Bumps [tokio-boring](https://github.com/cloudflare/boring) from 4.14.0 to 4.15.0.
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.14.0...v4.15.0)

---
updated-dependencies:
- dependency-name: tokio-boring
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 13:33:54 -05:00
Oliver Gould e4307a61ee
chore(dependabot): group dependency updates (#3666)
This change updates the dependabot configuration to group certain ecosystems of
dependencies, especially rustls.
2025-02-27 10:14:58 -08:00
dependabot[bot] 46db23783d
build(deps): bump zerofrom from 0.1.5 to 0.1.6 (#3665)
Bumps [zerofrom](https://github.com/unicode-org/icu4x) from 0.1.5 to 0.1.6.
- [Release notes](https://github.com/unicode-org/icu4x/releases)
- [Changelog](https://github.com/unicode-org/icu4x/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unicode-org/icu4x/commits)

---
updated-dependencies:
- dependency-name: zerofrom
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 17:28:44 +00:00
dependabot[bot] ec6239f6b7
build(deps): bump litemap from 0.7.4 to 0.7.5 (#3664)
Bumps [litemap](https://github.com/unicode-org/icu4x) from 0.7.4 to 0.7.5.
- [Release notes](https://github.com/unicode-org/icu4x/releases)
- [Changelog](https://github.com/unicode-org/icu4x/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unicode-org/icu4x/commits)

---
updated-dependencies:
- dependency-name: litemap
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 09:20:28 -08:00
dependabot[bot] f3ba58d2a9
build(deps): bump uuid from 1.15.0 to 1.15.1 (#3663)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.15.0 to 1.15.1.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.15.0...v1.15.1)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 09:20:11 -08:00
dependabot[bot] 33fc3e3f0f
build(deps): bump zerofrom-derive from 0.1.5 to 0.1.6 (#3662)
Bumps [zerofrom-derive](https://github.com/unicode-org/icu4x) from 0.1.5 to 0.1.6.
- [Release notes](https://github.com/unicode-org/icu4x/releases)
- [Changelog](https://github.com/unicode-org/icu4x/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unicode-org/icu4x/commits)

---
updated-dependencies:
- dependency-name: zerofrom-derive
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 09:18:34 -08:00
dependabot[bot] 3119806c85
build(deps): bump codecov/codecov-action from 5.3.1 to 5.4.0 (#3661)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.3.1 to 5.4.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](13ce06bfc6...0565863a31)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 09:18:12 -08:00
katelyn martin 5945c92447
chore(app/trace-collector): remove `Default` bound (#3660)
see #3651 and linkerd/linkerd2#8733.

#3651 missed this unused trait bound, which we want to loosen
to account for changes in hyper's api.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-26 08:18:00 -08:00
dependabot[bot] 3597b90ce2
build(deps): bump actions/download-artifact from 4.1.8 to 4.1.9 (#3658)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.8 to 4.1.9.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](fa0a91b85d...cc20338598)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-26 10:07:58 -05:00
dependabot[bot] fcb5773b19
build(deps): bump uuid from 1.14.0 to 1.15.0 (#3659)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-26 10:07:38 -05:00
katelyn martin 8daafde63b
chore(proxy/identity-client): remove `Default` bounds (#3653)
https://github.com/linkerd/linkerd2/issues/8733 for more information.

see also, https://github.com/linkerd/linkerd2-proxy/pull/3651 for
another related pull request.

in hyper 1.x, `Incoming` bodies do not provide a `Default`
implementation. compare the trait implementations here:

* https://docs.rs/hyper/0.14.31/hyper/body/struct.Body.html#impl-Default-for-Body
* https://docs.rs/hyper/latest/hyper/body/struct.Incoming.html#trait-implementations

this commit removes these bounds from
`linkerd_proxy_identity_client::Certify<C, S>`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-26 10:06:56 -05:00
katelyn martin 9aca7b6894
nit(opencensus): format use statements (#3652)
this commit makes some superficial adjustments to import statements in
`linkerd-opencensus`. we have a convention of using crate-level symbol
groupings in `use` statements. this commit follows that convention.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-25 16:02:28 -05:00
katelyn martin 4df3d57c32
chore(service-profiles): remove `Default` bounds (#3657)
see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

see also, #3651 #3653, #3654, and #3655 for some related pull requests.

in hyper 1.x, `Incoming` bodies do not provide a `Default`
implementation. compare the trait implementations here:

* https://docs.rs/hyper/0.14.31/hyper/body/struct.Body.html#impl-Default-for-Body
* https://docs.rs/hyper/latest/hyper/body/struct.Incoming.html#trait-implementations

this commit removes `Default` bounds from `Client<R, S>` used to create
watches on service profiles.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-25 16:01:39 -05:00
katelyn martin f054e54bce
chore(proxy/api-resolve): remove `Default` bounds (#3656)
see https://github.com/linkerd/linkerd2/issues/8733 for more information.

see also, #3651 #3653, and #3654 for some related pull requests.

in hyper 1.x, `Incoming` bodies do not provide a `Default`
implementation. compare the trait implementations here:

* https://docs.rs/hyper/0.14.31/hyper/body/struct.Body.html#impl-Default-for-Body
* https://docs.rs/hyper/latest/hyper/body/struct.Incoming.html#trait-implementations

this commit removes `Default` bounds from `Resolve<S>`.

this means that in `linkerd-app`, we can invoke
`new_recover_default()` when using hyper 1.x (_see #3504_)

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-25 16:01:28 -05:00
katelyn martin 09a0c0f4eb
chore(app/outbound): remove `Default` bounds (#3655)
see https://github.com/linkerd/linkerd2/issues/8733 for more information.

see also, #3651 #3653, and #3654 for some related pull requests.

in hyper 1.x, `Incoming` bodies do not provide a `Default` implementation. compare the trait implementations here:

* https://docs.rs/hyper/0.14.31/hyper/body/struct.Body.html#impl-Default-for-Body
* https://docs.rs/hyper/latest/hyper/body/struct.Incoming.html#trait-implementations

this commit removes `Default` bounds from policy lookup in the outbound
proxy. this means that in `linkerd-app`, we can invoke
`Outbound::build_policies()` when using hyper 1.x (_see #3504_)

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-25 16:01:16 -05:00
katelyn martin 1a12be5eb6
chore(app/inbound): remove `Default` bounds (#3654)
see https://github.com/linkerd/linkerd2/issues/8733 for more information.

see also, #3651 and #3653 for some related pull requests.

in hyper 1.x, `Incoming` bodies do not provide a `Default`
implementation. compare the trait implementations here:

* https://docs.rs/hyper/0.14.31/hyper/body/struct.Body.html#impl-Default-for-Body
* https://docs.rs/hyper/latest/hyper/body/struct.Incoming.html#trait-implementations

this commit removes `Default` bounds from policy lookup in the inbound
proxy.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-25 16:00:56 -05:00
katelyn martin 5ee4f711cf
chore(app/trace_collector): remove `Default` bounds (#3651)
see https://github.com/linkerd/linkerd2/issues/8733 for more information.

in hyper 1.x, `Incoming` bodies do not provide a `Default`
implementation. compare the trait implementations here:

* https://docs.rs/hyper/0.14.31/hyper/body/struct.Body.html#impl-Default-for-Body
* https://docs.rs/hyper/latest/hyper/body/struct.Incoming.html#trait-implementations

this commit removes these bounds from the
`linkerd_app::trace_collector::otel_collector::SpanExporter<T, S>` and
other connected functions.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-25 16:00:28 -05:00
dependabot[bot] ea8a970c70
build(deps): bump either from 1.13.0 to 1.14.0 (#3649)
Bumps [either](https://github.com/rayon-rs/either) from 1.13.0 to 1.14.0.
- [Commits](https://github.com/rayon-rs/either/compare/1.13.0...1.14.0)

---
updated-dependencies:
- dependency-name: either
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 12:01:14 -05:00
dependabot[bot] bb0a1ec57d
build(deps): bump portable-atomic from 1.10.0 to 1.11.0 (#3648)
Bumps [portable-atomic](https://github.com/taiki-e/portable-atomic) from 1.10.0 to 1.11.0.
- [Release notes](https://github.com/taiki-e/portable-atomic/releases)
- [Changelog](https://github.com/taiki-e/portable-atomic/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/portable-atomic/compare/v1.10.0...v1.11.0)

---
updated-dependencies:
- dependency-name: portable-atomic
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 12:01:03 -05:00
katelyn martin 8e5d0fdc0c
chore(tls): remove redundant i/o bounds (#3647)
this commit removes a redundant set of trait bounds from
`linkerd_tls::Client<L, C>`'s `tower::Service<T>` implementation.

this client type is generic over a `C`-typed `MakeConnection`. this
trait is effectively an alias for particular services, and already by
definition is prerequisite upon `Connection` responses that are
an asynchronous reader/writer.

see the definition of the trait, here:

```rust
// linkerd/stack/src/connect.rs

pub trait MakeConnection<T> {
    /// An I/O type that represents a connection to the remote endpoint.
    type Connection: AsyncRead + AsyncWrite;

    /// Metadata associated with the established connection.
    type Metadata;

    type Error: Into<Error>;

    type Future: Future<Output = Result<(Self::Connection, Self::Metadata), Self::Error>>;

    /// Determines whether the connector is ready to establish a connection.
    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;

    /// Establishes a connection.
    fn connect(&mut self, t: T) -> Self::Future;

    // contd...
}
```

thus, we can remove these bounds from the tls client. the connection is
already, by virtue of `C: MakeConnection`, an `AsyncRead + AsyncWrite`
type.

see https://github.com/linkerd/linkerd2/issues/8733.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-24 11:03:23 -05:00
dependabot[bot] 78e6c7a40c
build(deps): bump actions/upload-artifact from 4.6.0 to 4.6.1 (#3646)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.0 to 4.6.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](65c4c4a1dd...4cec3d8aa0)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 09:30:06 -05:00
dependabot[bot] d0c10e02d6
build(deps): bump EmbarkStudios/cargo-deny-action from 2.0.5 to 2.0.6 (#3645)
Bumps [EmbarkStudios/cargo-deny-action](https://github.com/embarkstudios/cargo-deny-action) from 2.0.5 to 2.0.6.
- [Release notes](https://github.com/embarkstudios/cargo-deny-action/releases)
- [Commits](13fd9ef18c...0484eedcba)

---
updated-dependencies:
- dependency-name: EmbarkStudios/cargo-deny-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 09:29:53 -05:00
dependabot[bot] f86d5f9e88
build(deps): bump pem from 3.0.4 to 3.0.5 (#3644)
Bumps [pem](https://github.com/jcreekmore/pem-rs) from 3.0.4 to 3.0.5.
- [Changelog](https://github.com/jcreekmore/pem-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jcreekmore/pem-rs/compare/v3.0.4...v3.0.5)

---
updated-dependencies:
- dependency-name: pem
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 09:29:41 -05:00
dependabot[bot] c5c33d580d
build(deps): bump ring from 0.17.9 to 0.17.11 (#3643)
Bumps [ring](https://github.com/ctz/ring) from 0.17.9 to 0.17.11.
- [Release notes](https://github.com/ctz/ring/releases)
- [Commits](https://github.com/ctz/ring/compare/0.17.9...0.17.11)

---
updated-dependencies:
- dependency-name: ring
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 09:29:23 -05:00
dependabot[bot] f24e13c983
build(deps): bump libc from 0.2.169 to 0.2.170 (#3642)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.169 to 0.2.170.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.170/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.169...0.2.170)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 09:29:11 -05:00
dependabot[bot] a8dea3cd05
build(deps): bump uuid from 1.13.2 to 1.14.0 (#3641)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.13.2 to 1.14.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/v1.13.2...v1.14.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 09:28:59 -05:00
dependabot[bot] 6fd566715b
build(deps): bump flate2 from 1.0.35 to 1.1.0 (#3640)
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.0.35 to 1.1.0.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Changelog](https://github.com/rust-lang/flate2-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.35...1.1.0)

---
updated-dependencies:
- dependency-name: flate2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 09:28:42 -05:00
Zahari Dichev 46ea686439
chore(transport): Ignore TCP_USER_TIMEOUT on non-Linux systems and warn (#3628)
Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2025-02-21 18:40:14 +00:00
Zahari Dichev fc4efc90e5
chore(app): make spire compilation possible for non-linux targets (#3627)
Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2025-02-21 08:56:01 -08:00
dependabot[bot] 2656df4be8
build(deps): bump unicode-ident from 1.0.16 to 1.0.17 (#3635)
Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.16 to 1.0.17.
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.16...1.0.17)

---
updated-dependencies:
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-21 10:16:55 -05:00
dependabot[bot] c08124d358
build(deps): bump serde from 1.0.217 to 1.0.218 (#3637)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.217 to 1.0.218.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.218)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-21 10:16:45 -05:00
dependabot[bot] 6b76a8552a
build(deps): bump log from 0.4.25 to 0.4.26 (#3638)
Bumps [log](https://github.com/rust-lang/log) from 0.4.25 to 0.4.26.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.25...0.4.26)

---
updated-dependencies:
- dependency-name: log
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-21 10:16:24 -05:00
dependabot[bot] 09e7918133
build(deps): bump cc from 1.2.14 to 1.2.15 (#3639)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.14 to 1.2.15.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.14...cc-v1.2.15)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-21 10:16:11 -05:00
dependabot[bot] e3f6fb7eae
build(deps): bump anyhow from 1.0.95 to 1.0.96 (#3636)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.95 to 1.0.96.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.95...1.0.96)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-21 10:15:22 -05:00
dependabot[bot] 0ca220b37b
build(deps): bump tokio-boring from 4.13.0 to 4.14.0 (#3631)
Bumps [tokio-boring](https://github.com/cloudflare/boring) from 4.13.0 to 4.14.0.
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.13.0...v4.14.0)

---
updated-dependencies:
- dependency-name: tokio-boring
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: katelyn martin <kate@buoyant.io>
2025-02-20 12:24:06 -05:00
dependabot[bot] 733885aed8
build(deps): bump EmbarkStudios/cargo-deny-action from 2.0.4 to 2.0.5 (#3629)
Bumps [EmbarkStudios/cargo-deny-action](https://github.com/embarkstudios/cargo-deny-action) from 2.0.4 to 2.0.5.
- [Release notes](https://github.com/embarkstudios/cargo-deny-action/releases)
- [Commits](e2f4ede4a4...13fd9ef18c)

---
updated-dependencies:
- dependency-name: EmbarkStudios/cargo-deny-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-20 11:29:01 -05:00
dependabot[bot] bfa5d8bd8c
build(deps): bump serde_json from 1.0.138 to 1.0.139 (#3632)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.138 to 1.0.139.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.138...v1.0.139)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-20 11:28:45 -05:00
dependabot[bot] 4d5a9e45f3
build(deps): bump hickory-resolver from 0.24.3 to 0.24.4 (#3630)
Bumps [hickory-resolver](https://github.com/hickory-dns/hickory-dns) from 0.24.3 to 0.24.4.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.3...v0.24.4)

---
updated-dependencies:
- dependency-name: hickory-resolver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-20 11:28:25 -05:00
dependabot[bot] f619f0fc0a
build(deps): bump hickory-proto from 0.24.3 to 0.24.4 (#3634)
Bumps [hickory-proto](https://github.com/hickory-dns/hickory-dns) from 0.24.3 to 0.24.4.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.3...v0.24.4)

---
updated-dependencies:
- dependency-name: hickory-proto
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-20 11:28:04 -05:00
dependabot[bot] 25324b6a15
build(deps): bump boring-sys from 4.13.0 to 4.14.0 (#3633)
Bumps [boring-sys](https://github.com/cloudflare/boring) from 4.13.0 to 4.14.0.
- [Release notes](https://github.com/cloudflare/boring/releases)
- [Changelog](https://github.com/cloudflare/boring/blob/master/RELEASE_NOTES)
- [Commits](https://github.com/cloudflare/boring/compare/v4.13.0...v4.14.0)

---
updated-dependencies:
- dependency-name: boring-sys
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-20 11:27:33 -05:00
Zahari Dichev b8cc2d0878
chore(transport): User socket2 to obtain orig_dst (#3626)
Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2025-02-19 11:05:38 -08:00
dependabot[bot] 30a9f24a98
build(deps): bump typenum from 1.17.0 to 1.18.0 (#3624)
Bumps [typenum](https://github.com/paholg/typenum) from 1.17.0 to 1.18.0.
- [Release notes](https://github.com/paholg/typenum/releases)
- [Changelog](https://github.com/paholg/typenum/blob/main/CHANGELOG.md)
- [Commits](https://github.com/paholg/typenum/compare/v1.17.0...v1.18.0)

---
updated-dependencies:
- dependency-name: typenum
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-18 11:16:46 -05:00
dependabot[bot] b255c8251c
build(deps): bump uuid from 1.13.1 to 1.13.2 (#3625)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.13.1 to 1.13.2.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/1.13.1...v1.13.2)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-18 11:16:40 -05:00
dependabot[bot] 04fd64e31c
build(deps): bump tempfile from 3.17.0 to 3.17.1 (#3623)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.17.0 to 3.17.1.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.17.0...v3.17.1)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-18 11:16:27 -05:00
katelyn martin 48748be0e8
refactor(app/core): prepare rescue body for http-body upgrade (#3616)
this commit makes some minor alterations to our error recovery body
middleware. see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

this commit removes an `assert!` statement from the implementation of
`<Response<R, B> as Body>::poll_data()`. see the documentation of
`Body::poll_frame()`:

> Once the end of the stream is reached, implementations should
> continue to return [`Poll::Ready(None)`].

1090bfff26 (diff-33aabe8c2aaa7614022addf244245e09bbff576a67a9ae3c6938c8a868201d36R60-R61)

to do this, this commit introduces a distinct terminal state
`Inner::Rescued` to represent when the underlying `B`-typed body has
yielded an error and been rescued. once in this state the body will
yield no more data frames, instead yielding a collection of trailers
describing the mid-stream error that was encountered by the underlying
body.

the call to `R::rescue` is also moved down into the helper function fka
`grpc_trailers()`. this helps the function follow the grain of our
"state machine" a little more directly.

see #3615, #3614, and #3611 for pretext to this change.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-17 11:53:25 -05:00
dependabot[bot] 65f9d28a11
build(deps): bump cc from 1.2.12 to 1.2.14 (#3617)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.12 to 1.2.14.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.12...cc-v1.2.14)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 08:39:11 -08:00
dependabot[bot] 76f4e19c44
build(deps): bump tempfile from 3.16.0 to 3.17.0 (#3621)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.16.0 to 3.17.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.16.0...v3.17.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 11:00:59 -05:00
dependabot[bot] 508791dce8
build(deps): bump equivalent from 1.0.1 to 1.0.2 (#3620)
Bumps [equivalent](https://github.com/indexmap-rs/equivalent) from 1.0.1 to 1.0.2.
- [Commits](https://github.com/indexmap-rs/equivalent/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: equivalent
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 11:00:45 -05:00
dependabot[bot] 2e3c6c3cfd
build(deps): bump smallvec from 1.13.2 to 1.14.0 (#3619)
Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.13.2 to 1.14.0.
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.13.2...v1.14.0)

---
updated-dependencies:
- dependency-name: smallvec
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 11:00:32 -05:00
dependabot[bot] d2425c8c56
build(deps): bump ring from 0.17.8 to 0.17.9 (#3618)
Bumps [ring](https://github.com/briansmith/ring) from 0.17.8 to 0.17.9.
- [Commits](https://github.com/briansmith/ring/commits)

---
updated-dependencies:
- dependency-name: ring
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-14 07:20:13 -08:00
katelyn martin b883089ac9
refactor(app/core): a unit test suite for rescue body (#3615)
`linkerd-app-core` includes an error recovery body middleware. this middleware will gracefully catch and report errors encountered when polling an inner body, and via an `R`-typed recovery strategy provided by the caller, will attempt to map the error to a gRPC status code denoting an error.

before we upgrade to hyper 1.0 in service of https://github.com/linkerd/linkerd2/issues/8733, we add some test coverage to ensure that we preserve the behavior of this middleware.

see:
* linkerd/linkerd2#8733
* #3614.

for historical context on this tower layer, see:
* #222
* #1246
* #1282

---

* refactor(http/retry): outline `ForwardCompatibleBody<B>`

in #3559 (4b53081), we introduced a backported `Frame<T>` type, and a
`ForwardCompatibleBody<B>` type that allows us to interact with a
`http_body::Body` circa 0.4.6 in terms of frame-based interfaces that
match those of the 1.0 interface.

see linkerd/linkerd2#8733 for more information on upgrading hyper.

in #3559, we narrowly added this as an internal submodule of the
`linkerd-http-retry` library. these facilities however, would have
utility in other places such as `linkerd-app-core`.

this commit pulls these compatibility shims out into a
`linkerd-http-body-compat` library so that they can be imported and
reused elsewhere.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(http/body-compat): tidy `combinators` imports

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): hoist `errors::code_header` helper

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): `l5d-*` constants are headers

these are header values. `http::HeaderName` has a const fn constructor,
so let's use that.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): grpc constants are headers

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): hoist `l5d-` and `grpc-` constants

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): outline `ResponseBody` middleware

we'll add a few tests for this middleware shortly.

this commit moves this middleware out into its own submodule.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): encapsulate `ResponseBody` enum

for other body middleware, we hide inner enum variants and their
constituent members by using the "inner" pattern.

this commit tweaks `ResponseBody` to follow suit, such that it now holds
an `Inner`, but does not expose its passthrough and rescue variants to
callers.

Signed-off-by: katelyn martin <kate@buoyant.io>

* docs(app/core): document `ResponseBody<R, B>`

this adds a small documentation comment describing what this type does.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/core): a unit test suite for rescue body

this commit introduces a test suite for our error recovery middleware.

this body middleware provides a mechanism to "rescue" errors, gracefully
mapping an error encountered when polling a gRPC body into e.g. trailers
with a gRPC status code.

before we upgrade this middleware in service of linkerd/linkerd2#8733,
we add some test coverage to ensure that we preserve this middleware.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-13 10:41:23 -05:00
dependabot[bot] 2f848a0604
build(deps): bump the opentelemetry group with 2 updates (#3607)
* build(deps): bump the opentelemetry group with 2 updates

Bumps the opentelemetry group with 2 updates: [opentelemetry](https://github.com/open-telemetry/opentelemetry-rust) and [opentelemetry_sdk](https://github.com/open-telemetry/opentelemetry-rust).


Updates `opentelemetry` from 0.27.1 to 0.28.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-rust/releases)
- [Commits](https://github.com/open-telemetry/opentelemetry-rust/compare/opentelemetry-0.27.1...opentelemetry-0.28.0)

Updates `opentelemetry_sdk` from 0.27.1 to 0.28.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-rust/releases)
- [Commits](https://github.com/open-telemetry/opentelemetry-rust/compare/opentelemetry_sdk-0.27.1...opentelemetry_sdk-0.28.0)

---
updated-dependencies:
- dependency-name: opentelemetry
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry
- dependency-name: opentelemetry_sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: opentelemetry
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(deps): Fix build breakages from opentelemetry-sdk 0.28

The changes here are fairly small, with the main two being a change to an import path and replacing a privated `new` function with a builder.

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Scott Fleener <scott@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Scott Fleener <scott@buoyant.io>
2025-02-13 07:13:05 -08:00
katelyn martin faa42fddeb
refactor(http/retry): outline `ForwardCompatibleBody<B>` (#3614)
* refactor(http/retry): outline `ForwardCompatibleBody<B>`

in #3559 (4b53081), we introduced a backported `Frame<T>` type, and a
`ForwardCompatibleBody<B>` type that allows us to interact with a
`http_body::Body` circa 0.4.6 in terms of frame-based interfaces that
match those of the 1.0 interface.

see linkerd/linkerd2#8733 for more information on upgrading hyper.

in #3559, we narrowly added this as an internal submodule of the
`linkerd-http-retry` library. these facilities however, would have
utility in other places such as `linkerd-app-core`.

this commit pulls these compatibility shims out into a
`linkerd-http-body-compat` library so that they can be imported and
reused elsewhere.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(http/body-compat): tidy `combinators` imports

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-13 08:47:14 -05:00
dependabot[bot] e0a7121ad8
build(deps): bump rustls from 0.23.22 to 0.23.23 (#3612)
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.22 to 0.23.23.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.22...v/0.23.23)

---
updated-dependencies:
- dependency-name: rustls
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-12 11:54:36 -05:00
katelyn martin b2e8623419
refactor(mock/http-body): outline `MockBody` test body (#3611)
`MockBody` is a type that we use to implement tests for our
`peek_trailers::PeekTrailersBody<B>` body middleware. this is a useful
tool for mocking the polling outcomes of the inner body we wrap, which
would be useful for testing other `http_body::Body` middleware.

this commit moves `MockBody` out of `linkerd-http-retry`, and into a new
`linkerd-mock-http-body` crate. this is added as a test dependency for
the retry crate, and can now be used (rather than vendored) by other
bodies.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-12 07:14:15 -08:00
Oliver Gould 40e0cf4760
feat(outbound)!: disable 'hostname' label (#3606)
The 'hostname' label value is derived from the request URI and can be influenced
by applications. If a client uses a high cardinality of hostname values, this
leads to the proxy exporting many metrics and ultimately exhausting resources.

This change disables the 'hostname' label by default. A new field is outed to
the HTTP and TLS route parameters, `export_hostname_labels`, which can be used
to enable the 'hostname' label; however, this type is not yet configurable.
Changes are required to the proxy API and, ultimately, the policy controller, to
make this field configurable.

When the hostname is not exported, an empty label value is used.

BREAKING: The 'hostname' label is now disabled by default.
2025-02-12 07:13:29 -08:00
katelyn martin 570fc11743
refactor(app/core): remove unused reëxport (#3610)
Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-11 14:59:41 -05:00
dependabot[bot] fa94c2adeb
build(deps): bump oid-registry from 0.8.0 to 0.8.1 (#3608)
Bumps [oid-registry](https://github.com/rusticata/oid-registry) from 0.8.0 to 0.8.1.
- [Commits](https://github.com/rusticata/oid-registry/compare/oid-registry-0.8.0...oid-registry-0.8.1)

---
updated-dependencies:
- dependency-name: oid-registry
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 12:47:59 -05:00
Scott Fleener 3229f4b1ed
fix(opentelemetry): preserve span labels in traces (#3609)
A previous change enabling OpenTelmetry forgot to include attributes from the span itself, in addition to the request level spans as we do in the old OpenCensus exporter. This adds those attributes back in.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-02-11 16:03:26 +00:00
Oliver Gould d3cf6f3637
refactor(outbound): simplify http route metric labeling (#3604)
The outbound HTTP route labels use multiple ExtractParam implementations to
convert a matched route target to set of labels (using an HTTP request).

This change removes the RouteLabelExtract type, in favor of implementing label
extraction on the route target type directly.
2025-02-10 14:22:50 -08:00
Oliver Gould 768f5a75b0
chore(outbound): avoid allocation in TLS route labels (#3605) 2025-02-10 21:26:41 +00:00
dependabot[bot] 18d8257c48
build(deps): bump cmake from 0.1.53 to 0.1.54 (#3603)
Bumps [cmake](https://github.com/rust-lang/cmake-rs) from 0.1.53 to 0.1.54.
- [Release notes](https://github.com/rust-lang/cmake-rs/releases)
- [Changelog](https://github.com/rust-lang/cmake-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cmake-rs/compare/v0.1.53...v0.1.54)

---
updated-dependencies:
- dependency-name: cmake
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 11:15:43 -05:00
dependabot[bot] 7c3ffa3a86
build(deps): bump hickory-proto from 0.24.2 to 0.24.3 (#3602)
Bumps [hickory-proto](https://github.com/hickory-dns/hickory-dns) from 0.24.2 to 0.24.3.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.3/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.2...v0.24.3)

---
updated-dependencies:
- dependency-name: hickory-proto
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 11:14:56 -05:00
dependabot[bot] 5880a9d49a
build(deps): bump data-encoding from 2.7.0 to 2.8.0 (#3601)
Bumps [data-encoding](https://github.com/ia0/data-encoding) from 2.7.0 to 2.8.0.
- [Commits](https://github.com/ia0/data-encoding/compare/v2.7.0...v2.8.0)

---
updated-dependencies:
- dependency-name: data-encoding
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 11:14:50 -05:00
dependabot[bot] b69b3442b2
build(deps): bump hickory-resolver from 0.24.2 to 0.24.3 (#3600)
Bumps [hickory-resolver](https://github.com/hickory-dns/hickory-dns) from 0.24.2 to 0.24.3.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.3/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.2...v0.24.3)

---
updated-dependencies:
- dependency-name: hickory-resolver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 11:14:26 -05:00
dependabot[bot] c96efbe1cc
build(deps): bump once_cell from 1.20.2 to 1.20.3 (#3599)
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.20.2 to 1.20.3.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.2...v1.20.3)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-07 11:51:04 -05:00
katelyn martin 4b53081a84
feat(http/retry): model `ReplayBody<B>` with `Frame<T>` (#3598)
pr #3559 (dd4fbcdb) refactored our trailer peeking body middleware to
model its buffering in terms of the `Frame<T>` type used in
`http-body`'s 1.0 release.

this branch performs a similar change for the other piece of body
middleware that super linkerd's retry facilities: `ReplayBody<B>`. the
inner body `B` is now wrapped in the `ForwardCompatibleBody<B>` adapter,
and we now poll it in terms of frames.

NB: polling the underlying in terms of frames has a subtle knock-on
effect regarding when we observe the trailers, in the liminal period
between this refactor and the subsequent upgrade to hyper 1.0, whilst we
must still implement the existing 0.4 interface for `Body` that includes
`poll_trailers()`.

see the comment above `replay_trailers` for more on this, describing why
we now initialize this to `true`. relatedly, this is why we no longer
delegate down to `B::poll_trailers` ourselves. it will have already been
called by our adapter.

`ReplayBody::is_end_stream()` now behaves identically when initially
polling a body compared to subsequent replays. this is fine, as
`is_end_stream()` is a hint that facilitates optimizations
(https://github.com/hyperium/http-body/pull/143). we do still report the end properly, we just
won't be quite as prescient on the initial playthrough.

in the same manner as the existing `frame()` method mimics
`http_body_util::BodyExt::frame()`, this branch introduces
a new `ForwardCompatibleBody::poll_frame()` method.

this allows us to poll the compatibility layer for a `Frame<T>`.

see:
- https://github.com/linkerd/linkerd2/issues/8733.
- https://github.com/linkerd/linkerd2-proxy/pull/3559

---

* nit(http/retry): install tracing subscriber in tests

some tests do not set up a tracing subscriber, because they do not use
the shared `Test::new()` helper function used elsewhere in this test
suite.

to provide a trace of the test's execution in the event of a failure,
initialize a tracing subscriber in some additional unit tests.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): `ForwardCompatibleBody<B>` exposes hints

this commit removes the `cfg(test)` gate on the method exposing
`B::is_end_stream()`, and introduces another method also exposing the
`size_hint()` method.

we will want these in order to implement these methods for
`ReplayBody<B>`.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): `ForwardCompatibleBody::poll_frame()`

in the same manner as the existing `frame()` method mimics
`http_body_util::BodyExt::frame()`, this commit introduces
a new `ForwardCompatibleBody::poll_frame()` method.

this allows us to poll the compatibility layer for a `Frame<T>`.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): `ReplayBody<B>` polls for frames

pr #3559 (dd4fbcd) refactored our trailer peeking body middleware to
model its buffering in terms of the `Frame<T>` type used in
`http-body`'s 1.0 release.

this commit performs a similar change for the other piece of body
middleware that super linkerd's retry facilities: `ReplayBody<B>`. the
inner body `B` is now wrapped in the `ForwardCompatibleBody<B>` adapter,
and we now poll it in terms of frames.

NB: polling the underlying in terms of frames has a subtle knock-on
effect regarding when we observe the trailers, in the liminal period
between this refactor and the subsequent upgrade to hyper 1.0, whilst we
must still implement the existing 0.4 interface for `Body` that includes
`poll_trailers()`.

see the comment above `replay_trailers` for more on this, describing why
we now initialize this to `true`. relatedly, this is why we now longer
delegate down to `B::poll_trailers` ourselves. it will have already been
called by our adapter.

`ReplayBody::is_end_stream()` now behaves identically when initially
polling a body compared to subsequent replays. this is fine, as
`is_end_stream()` is a hint that facilitates optimizations
(hyperium/http-body#143). we do still report the end properly, we just
won't be quite as prescient on the initial playthrough.

see:
- https://github.com/linkerd/linkerd2/issues/8733.
- https://github.com/linkerd/linkerd2-proxy/pull/3559

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): `is_end_stream()` traces

this commit introduces some trace-level diagnostics tracking how the
replay body has determined whether or not it has reached the end of the
stream.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(http/retry): capitalize trace event messages

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-06 16:00:38 +00:00
katelyn martin c4e0fd2bd4
refactor(http/retry): outline bounded replay buffer (#3597)
the `ReplayBody<B>` middleware makes use of a `BufList` type to hold a
reference to bytes yielded by the inner body `B`. a `Data` enum is
composed on top to this, to allow bodies to either return (a) a replay
of a previous body, or (b) the iniial bytes yielded by the original
body.

this branch also takes the step of moving some code out of the
`ReplayBody::poll_data(..)` trait method along with inlining
`BufList::push_chunk(..)` , a small helper function that is only used
once.

this is intended to consolidate code related to buffering data yielded
by the underlying `B`-typed body, and extricate logic concerning the
bounding of this buffer from the now defunct `Body::poll_data()` trait
method.

see https://github.com/linkerd/linkerd2/issues/8733 for more information
about upgrading the proxy to hyper 1.0.

this will help make subsequent changes to the model of `ReplayBody<B>`
its corresponding `Body` implementation more reviewable, by proactively
reorganizing things in advance.

---

* refactor(http/retry): outline replay buffer

the replay body uses this `BufList` type to hold a reference to bytes
yielded by the inner body `B`.

the `Data` enum is composed on top to this, to allow bodies to either
return a replay of a previous body, or the iniial bytes yielded by the
original body.

this is all relatively self-contained, so we can move this into a small
submodule.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): outline replay body buffering

this commit moves some code out of the `ReplayBody::poll_data(..)` trait
method.

this bit of code is where we take a chunk of a data yielded by the inner
body, and push it into our replay buffer. if the capacity is exceeded,
we flush the buffer. in either case, the code copies the chunk into a
cheaply cloneable, contiguous `Bytes`.

this is all related to the buffer, so we move it there.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): inline `BufList::push_chunk`

`push_chunk` is a small helper function that is only used once. now that
we have moved our buffering code alongside this type, it's more
straightforward to inline this function.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): rename `BufList` to `Replay`

this structure is responsible for acting as the `bytes::Buf` buffer for
the replay of the initial body.

this commit renames this to articulate that relationship more directly.

Signed-off-by: katelyn martin <kate@buoyant.io>

* docs(http/retry): polish `Replay` documentation

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-06 10:50:27 -05:00
dependabot[bot] 4f7f7156e9
build(deps): bump cc from 1.2.11 to 1.2.12 (#3592)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.11 to 1.2.12.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.11...cc-v1.2.12)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-05 12:36:02 -05:00
dependabot[bot] d3f2c120fa
build(deps): bump symbolic-common from 12.13.3 to 12.13.4 (#3593)
Bumps [symbolic-common](https://github.com/getsentry/symbolic) from 12.13.3 to 12.13.4.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.13.3...12.13.4)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-05 11:59:55 -05:00
dependabot[bot] 733ee21abf
build(deps): bump tj-actions/changed-files from 45.0.6 to 45.0.7 (#3594)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 45.0.6 to 45.0.7.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](d6e91a2266...dcc7a0cba8)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-05 11:59:31 -05:00
dependabot[bot] 5b2a4b5f42
build(deps): bump symbolic-demangle from 12.13.3 to 12.13.4 (#3595)
Bumps [symbolic-demangle](https://github.com/getsentry/symbolic) from 12.13.3 to 12.13.4.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.13.3...12.13.4)

---
updated-dependencies:
- dependency-name: symbolic-demangle
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-05 11:59:21 -05:00
dependabot[bot] 6633a3f1db
build(deps): bump uuid from 1.12.1 to 1.13.1 (#3596)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.12.1 to 1.13.1.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/1.12.1...1.13.1)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-05 11:59:11 -05:00
katelyn martin 7eecfb425b
refactor(http/retry): use `Poll<T>` mapping methods (#3586)
this commit makes some small, admittedly subjective tweaks to
`ReplayBody::poll_trailers(..)`.

we can make use of the `map_ok` and `map_err` methods that exist to map
`Poll::Ready<Result<T, E>>`'s inner `T` to some `U` (in our case, to
record the trailers for later replay), and to map the error type into a
boxed `Error`.

this is a minor tweak, front-running other work to port the
`ReplayBody<B>` to http-body 1.0. see
https://github.com/linkerd/linkerd2/issues/8733.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-04 16:55:55 +00:00
katelyn martin dc53def982
refactor(http/retry): replayed body is not optional (#3585)
`ReplayBody<B>` is slightly inconsistent about how it represents the
exhaustion of the inner `B`-typed body.

first, in `poll_data()` we poll the inner body, and note that we
consider a `None` value for `BodyState::rest` to mean that there is no
more work to do.

```rust
// Poll the inner body for more data. If the body has ended, remember
// that so that future clones will not try polling it again (as
// described above).
let mut data = {
    // Get access to the initial body. If we don't have access to the
    // inner body, there's no more work to do.
    let rest = match state.rest.as_mut() {
	Some(rest) => rest,
	None => return Poll::Ready(None),
    };
    // ...
};
```

then, in `Body::is_end_stream()`, we write the following to check that
the stream is done:

```rust
let is_inner_eos = self
    .state
    .as_ref()
    .and_then(|state| state.rest.as_ref().map(Body::is_end_stream))
    .unwrap_or(false);
```

note in particular the call to `Option::and_then(..)`.

this means that, should the inner body be `None`, we will begin
reporting the stream as **not** finished. this is backwards!

this commit makes a change to the definition of `BodyState<B>`. it no
longer treats its inner body as optional. we never drop the inner body
`B`, to facilitate gracefully replaying bodies that were interrupted
when initially being polled.

a bare `B` means that various bits of control are now simpler, without
having to account for the `Option<T>` state.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-02-04 11:39:16 -05:00
dependabot[bot] e18d0d4acc
build(deps): bump bytes from 1.9.0 to 1.10.0 (#3591)
Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: bytes
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-04 09:11:25 -05:00
dependabot[bot] 0df44c9a70
build(deps): bump syn from 2.0.96 to 2.0.98 (#3589)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.96 to 2.0.98.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.96...2.0.98)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 09:24:59 -05:00
dependabot[bot] dc4c5a4e49
build(deps): bump async-trait from 0.1.85 to 0.1.86 (#3587)
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.85 to 0.1.86.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.85...0.1.86)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 09:24:44 -05:00
dependabot[bot] 9f7a3d95a8
build(deps): bump pin-project from 1.1.8 to 1.1.9 (#3588)
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 1.1.8 to 1.1.9.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v1.1.8...v1.1.9)

---
updated-dependencies:
- dependency-name: pin-project
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 09:24:30 -05:00
dependabot[bot] d95d0c81f7
build(deps): bump cc from 1.2.10 to 1.2.11 (#3590)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.10 to 1.2.11.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.10...cc-v1.2.11)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 09:24:13 -05:00
Scott Fleener 4e791fe5b8
Support OTEL_RESOURCE_ATTRIBUTES in the proxy (#3580)
This environment variable is definted by the OpenTelemetry conventions as a way of specifying additional resource attributes to be included in traces: https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#general-sdk-configuration

Note that this is parallel to LINKERD2_PROXY_TRACE_EXTRA_ATTRIBUTES, which is meant for common attributes that should always be provided by the proxy (pod UID, contianer name, etc.). We do not expect users to override that one, as OTEL_RESOURCE_ATTRIBUTES is the conventional way of specifying custom attributes.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-01-31 14:47:14 +00:00
dependabot[bot] 63dce670a0
build(deps): bump rustls from 0.23.21 to 0.23.22 (#3584)
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.21 to 0.23.22.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.21...v/0.23.22)

---
updated-dependencies:
- dependency-name: rustls
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-31 09:23:29 -05:00
katelyn martin afda8a7b30
feat(http/retry): add more replay body test coverage (#3583)
see https://github.com/linkerd/linkerd2/issues/8733.

we are currently in the process of upgrading our hyper, http, and http-body dependencies to their 1.0 major releases.

this branch introduces additional test coverage, and further refines existing test coverage, concerning how a `ReplayBody<B>` behaves when it reaches the "end of stream" of its internal `B`-typed body.

additional assertions are added to show that bodies with trailers may be replayed an arbitrary number of times, and that capacity errors occur precisely at their expected boundary. additional assertions are added to confirm that `ReplayBody::is_capped()` reports these conditions properly.

this branch also notably outlines the unit test suite into a separate file, due to its size. as a result, reviewers are encouraged to walk through this branch on a commit-by-commit basis when reading these changes.

i noticed some relatively minor issues with `is_end_stream()` and `size_hint()` while i was reviewing this middleware, in preparation to port it to http-body 1.0. i have left `TODO` comments noting where today's behavior is slightly askew, but _intentionally avoided_ fixing them here. my goal on that front is to highlight those wrinkles so that later fixes to these edges are more easily reviewable.

---

* refactor(http/retry): outline `ReplayBody<B>` unit tests

there are more than 500 lines of unit tests. let's move them into a
submodule, for convenience.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(http/retry): reorganize replay tests

this is a small cosmetic change reording some test helpers.

there is a common convention of affixing a banner comment above groups
of `impl T {}` blocks, which is useful when top-level blocks are folded
in an editor.

similarly, there is a convention of defining structures at the top of a
file.

this commit reorganizes the replay body tests to follow each of these
conventions.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(http/retry): test replays trailers twice

just to be extra sure!

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(http/retry): rename `trailers_only()` test

this is part of a family of other tests called `replays_one_chunk()`,
`replays_several_chunks()`, and `replays_trailers()`. let's name this
something that lines up with this convention.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): add a `TestBody` type

we have a unit test, called `eos_only_when_fully_replayed` that confirms
`Body::end_of_stream()` reports the stream ending properly.

soon, we aim to introduce additional test coverage that exercises this
when a body has trailers, as well. this will be useful for assurance
related to upgrading to http-body v1.x. see linkerd/linkerd2#8733 for
more information.

unfortunately, hyper 0.14's channel-backed body does not report itself
as having reached the end of the stream. this is an unfortunate quality
that prevents us from using `Test::new()`.

this commit adds a `TestBody` type that we can use in place of
`BoxBody::from_static(..)`, which boxes a static string, but does not
send trailers.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): add `is_end_stream()` coverage for trailers

this commit introduces additional test coverage that exercises
`is_end_stream()` when a replay body is wrapping a body with trailers.
this will be useful for assurance related to upgrading to http-body
v1.x. see linkerd/linkerd2#8733 for more information.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): add `is_capped()` test coverage

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): further refine capacity test coverage

we want to show that exceeding the capacity is the point at which
replays will fail.

this commit defines some constants to further communicate and encode
this relationship between the bytes sent, and the capacity of the replay
body.

further, it shortens the second frame sent so that we ensure precisely
when a body becomes capped.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): add `size_hint()` test coverage

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/retry): add todo comments concerning eos

for now, a replaying body that will not yield trailers must be polled to
the `None` before reporting itself as reaching the end of the stream.

this isn't hugely important, but does affect some test control flow.

leave two todo comments so that if/when upgrading to hyper 1.0, it is
clear that these are not load-bearing or otherwise expected behavior,
should this behavior be rectified.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-30 16:00:57 -05:00
katelyn martin 8d3762065c
docs(http/retry): document `ReplayBody::poll_*()` panics (#3582)
a `ReplayBody<B>` demands a particular contract of its users: one must not poll two bodies in parallel. this is currently mentioned as an implicit assumption on an internal helper function, `acquire_state<'a>`, here:

https://github.com/linkerd/linkerd2-proxy/blob/main/linkerd/http/retry/src/replay.rs#L127-L131

```rust
    /// # Panics
    ///
    /// This panics if another clone has currently acquired the state, based on
    /// the assumption that a retry body will not be polled until the previous
    /// request has been dropped.
    fn acquire_state<'a>(
        state: &'a mut Option<BodyState<B>>,
        shared: &Mutex<Option<BodyState<B>>>,
    ) -> &'a mut BodyState<B> {
        state.get_or_insert_with(|| shared.lock().take().expect("missing body state"))
    }
```

this commit echoes this sentiment on the relevant public-facing parts of this middleware: its `Body` trait methods.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-30 15:58:16 -05:00
Scott Fleener 00cba97276
Include extra trace attributes from env (#3483)
This allows us to include arbitrary values from the k8s downward API beyond just the pod labels that are included in the trace attributes file.

See https://github.com/linkerd/linkerd2/pull/13544 for the corresponding control plane change.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-01-30 15:37:15 -05:00
dependabot[bot] 2471aadd4b
build(deps): bump tempfile from 3.15.0 to 3.16.0 (#3581)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.15.0 to 3.16.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.15.0...v3.16.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-30 10:20:56 -05:00
katelyn martin f1817f8423
refactor(http/retry): update more `Body::data()` calls (#3573)
pr's #3564 and #3567, 1eb822f2 and 32042783 respectively, replaced uses
of defunct `http_body::Body` trait methods — namely, `data()` and
`trailers()`.

this commit updates two remaining uses of `data()` that were missed
in this initial pass.

see linkerd/linkerd2#8733 for more information.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-29 18:26:55 -08:00
dependabot[bot] 3ffda3f5af
build(deps): bump bumpalo from 3.16.0 to 3.17.0 (#3575)
Bumps [bumpalo](https://github.com/fitzgen/bumpalo) from 3.16.0 to 3.17.0.
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.16.0...3.17.0)

---
updated-dependencies:
- dependency-name: bumpalo
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 09:53:39 -05:00
dependabot[bot] e48fe47ad2
build(deps): bump httparse from 1.9.5 to 1.10.0 (#3577)
Bumps [httparse](https://github.com/seanmonstar/httparse) from 1.9.5 to 1.10.0.
- [Release notes](https://github.com/seanmonstar/httparse/releases)
- [Commits](https://github.com/seanmonstar/httparse/compare/v1.9.5...v1.10.0)

---
updated-dependencies:
- dependency-name: httparse
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 09:53:26 -05:00
dependabot[bot] 9ce0578aca
build(deps): bump serde_json from 1.0.137 to 1.0.138 (#3576)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.137 to 1.0.138.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.137...v1.0.138)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 09:53:13 -05:00
dependabot[bot] ce6568d617
build(deps): bump libfuzzer-sys from 0.4.8 to 0.4.9 (#3578)
Bumps [libfuzzer-sys](https://github.com/rust-fuzz/libfuzzer) from 0.4.8 to 0.4.9.
- [Changelog](https://github.com/rust-fuzz/libfuzzer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/libfuzzer/compare/0.4.8...0.4.9)

---
updated-dependencies:
- dependency-name: libfuzzer-sys
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 09:52:55 -05:00
dependabot[bot] 58eade9810
build(deps): bump x509-parser from 0.16.0 to 0.17.0 (#3579)
Bumps [x509-parser](https://github.com/rusticata/x509-parser) from 0.16.0 to 0.17.0.
- [Release notes](https://github.com/rusticata/x509-parser/releases)
- [Changelog](https://github.com/rusticata/x509-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rusticata/x509-parser/compare/x509-parser-0.16.0...x509-parser-0.17.0)

---
updated-dependencies:
- dependency-name: x509-parser
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 09:52:30 -05:00
katelyn martin 31d9e8f816
chore(deps/rand): update to `rand` v0.9.0 (#3574)
supersedes #3569.

this branch updates [`rand`](https://github.com/rust-random/rand) from 0.8.5 to 0.9.0.

- [release notes](https://github.com/rust-random/rand/releases)
- [changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [commits](https://github.com/rust-random/rand/compare/0.8.5...0.9.0)

note the changes to `rand::distr::weighted::Error`'s variants. see
https://github.com/rust-random/rand/pull/1382, and
https://github.com/rust-random/rand/pull/1470. in particular, this change:

https://github.com/rust-random/rand/pull/1382/files#diff-b0eb1b0ef894742b65e07f23af6cbeffae64ec8311adb6ea606603e978023e0cL116-R113

most other changes in this branch relate to the renaming of `thread_rng()` to `rng()`,
and `gen()` to `random()`.

---

* build(deps): bump rand from 0.8.5 to 0.9.0

Bumps [rand](https://github.com/rust-random/rand) from 0.8.5 to 0.9.0.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.8.5...0.9.0)

---
updated-dependencies:
- dependency-name: rand
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(exp-backoff): address `rand` breaking changes

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(pool/p2c): address `rand` breaking changes

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(distribute): address `rand` breaking changes

see https://github.com/rust-random/rand/pull/1382.

in particular, this part of the change:

https://github.com/rust-random/rand/pull/1382/files#diff-b0eb1b0ef894742b65e07f23af6cbeffae64ec8311adb6ea606603e978023e0cL116-R113

see also https://github.com/rust-random/rand/pull/1470.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/route): address `rand` breaking changes

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(exp-backoff): address `rand` breaking changes

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(deny.toml): skip previous `rand` dependencies

this addresses some ci errors related to duplicate dependencies:

```
error[duplicate]: found 2 duplicate entries for crate 'getrandom'
   ┌─ /github/workspace/Cargo.lock:75:1
   │
75 │ ╭ getrandom 0.2.15 registry+https://github.com/rust-lang/crates.io-index
76 │ │ getrandom 0.3.1 registry+https://github.com/rust-lang/crates.io-index
   │ ╰─────────────────────────────────────────────────────────────────────┘ lock entries
   │
```

Signed-off-by: katelyn martin <kate@buoyant.io>

* review(distribute): add `use` statement

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 16:31:25 -05:00
dependabot[bot] 2062f0c982
build(deps): bump unicode-ident from 1.0.15 to 1.0.16 (#3568)
Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.15 to 1.0.16.
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.15...1.0.16)

---
updated-dependencies:
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 12:01:54 -05:00
dependabot[bot] 271df709f0
build(deps): bump rustls-pki-types from 1.10.1 to 1.11.0 (#3572)
Bumps [rustls-pki-types](https://github.com/rustls/pki-types) from 1.10.1 to 1.11.0.
- [Release notes](https://github.com/rustls/pki-types/releases)
- [Commits](https://github.com/rustls/pki-types/compare/v/1.10.1...v/1.11.0)

---
updated-dependencies:
- dependency-name: rustls-pki-types
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 10:55:05 -05:00
dependabot[bot] 7477844520
build(deps): bump ryu from 1.0.18 to 1.0.19 (#3571)
Bumps [ryu](https://github.com/dtolnay/ryu) from 1.0.18 to 1.0.19.
- [Release notes](https://github.com/dtolnay/ryu/releases)
- [Commits](https://github.com/dtolnay/ryu/compare/1.0.18...1.0.19)

---
updated-dependencies:
- dependency-name: ryu
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 10:54:54 -05:00
dependabot[bot] 6184a1a994
build(deps): bump cmake from 0.1.52 to 0.1.53 (#3570)
Bumps [cmake](https://github.com/rust-lang/cmake-rs) from 0.1.52 to 0.1.53.
- [Release notes](https://github.com/rust-lang/cmake-rs/releases)
- [Changelog](https://github.com/rust-lang/cmake-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cmake-rs/compare/v0.1.52...v0.1.53)

---
updated-dependencies:
- dependency-name: cmake
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 10:54:42 -05:00
katelyn martin 32042783d9
refactor(http/retry): port remaining `ReplayBody` tests to `Frame<T>` (#3567)
based on #3564. see linkerd/linkerd2#8733.

this branch upgrades the remaining parts of the `ReplayBody<B>` test
suite to poll bodies in terms of `Frame<T>`s. 

1eb822f2e6

---

* refactor(http/retry): `replays_trailers()` uses `Frame<T>`

see https://github.com/linkerd/linkerd2/issues/8733.

this commit upgrades a test that uses defunct `data()` and `trailers()`
futures.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): `trailers_only()` uses `Frame<T>`

see https://github.com/linkerd/linkerd2/issues/8733.

this commit upgrades a test that uses defunct `data()` and `trailers()`
futures.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/retry): `ForwardCompatibleBody::is_end_stream()`

this commit adds a method that exposes the inner `B`-typed body's
`is_end_stream()` trait method, gated for use in tests.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): `body_to_string()` helper uses `Frame<T>`

this is a refactoring commit, upgrading more of the replay body test to
work in terms of `Frame<T>`. this updates the `body_to_string()` helper
in particular.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): `chunk()` helper uses `Frame<T>`

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-27 15:45:31 -05:00
katelyn martin 1eb822f2e6
refactor(http/retry): port some `ReplayBody` tests to `Frame<T>` (#3564)
see linkerd/linkerd2#8733.

pr #3559 introduced some compatibility facilities to allow us to write
code in terms of `http_body_util::BodyExt::frame()`, front-running the
upgrade to be performed in #3504.

some `ReplayBody` tests use the defunct `data()` and `trailers()`
interfaces. this branch ports _two_ such unit tests. other tests are
saved for a fast follow-on, as the `chunk(..)` and `read_to_string(..)`
helpers will need some slightly more involved tweaks.

dd4fbcdb6e

---

* refactor(http/retry): `replays_trailers()` uses `Frame<T>`

see https://github.com/linkerd/linkerd2/issues/8733.

this commit upgrades a test that uses defunct `data()` and `trailers()`
futures.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): `trailers_only()` uses `Frame<T>`

see https://github.com/linkerd/linkerd2/issues/8733.

this commit upgrades a test that uses defunct `data()` and `trailers()`
futures.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-27 15:43:58 -05:00
dependabot[bot] 0484917159
build(deps): bump codecov/codecov-action from 5.3.0 to 5.3.1 (#3566)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.3.0 to 5.3.1.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](0da7aa657d...13ce06bfc6)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 11:19:46 -08:00
dependabot[bot] 398348ec4d
build(deps): bump cpufeatures from 0.2.16 to 0.2.17 (#3565)
Bumps [cpufeatures](https://github.com/RustCrypto/utils) from 0.2.16 to 0.2.17.
- [Commits](https://github.com/RustCrypto/utils/compare/cpufeatures-v0.2.16...cpufeatures-v0.2.17)

---
updated-dependencies:
- dependency-name: cpufeatures
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 11:19:28 -08:00
katelyn martin dd4fbcdb6e
feat(http/retry): model `PeekTrailersBody<B>` with `Frame<T>` (#3559)
this branch contains a sequence of commits that refactor `PeekTrailersBody<B>`.

this branch is specifically focused on making this body middleware
forward-compatible with the 1.0 interface(s) of `http_body::Body` and
`http_body_util::BodyExt`.

it does this in two main steps: (1) temporarily vendoring `http_body::Frame<T>`
and providing a compatibility shim that provides a `frame()` method for a body,
and (2) modeling `PeekTrailersBody<B>` and its peeking logic in terms of this
`Frame<'a, T>` future.

---

* feat(http/retry): add `Frame<T>` compatibility facilities

this commit introduces a `compat` submodule to `linkerd-http-retry`.

this helps us frontrun the task of replacing all of the finicky control
flow in `PeekTrailersBody<B>` using the antiquated `data()` and
`trailers()` future combinators. instead, we can perform our peeking
in terms of an approximation of `http_body_util::BodyExt::frame()`.

to accomplish this, this commit vendors a copy of the `Frame<T>` type.
we can use this to preemptively model our peek body in terms of this
type, and move to the "real" version of it when we're upgrading in
pr #3504.

additionally, this commit includes a type called
`ForwardCompatibleBody<B>`, and a variant of the `Frame<'a, T>`
combinator. these are a bit boilerplate-y, admittedly, but the pleasant
part of this is that we have, in effect, migrated the trickiest body
middleware in advance of #3504. once we upgrade to http-body 1.0, all of
these types can be removed.

https://docs.rs/http-body-util/latest/http_body_util/trait.BodyExt.html#method.frame
https://docs.rs/http-body-util/0.1.2/src/http_body_util/combinators/frame.rs.html#10

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): `PeekTrailersBody<B>` uses `BodyExt::frame()`

this commit reworks `PeekTrailersBody<B>`.

the most important goal here is replacing the control flow of
`read_body()`, which polls a body using `BodyExt` future combinators
`data()` and `frame()` for up to two frames, with varying levels of
persistence depending on outcomes.

to quote #3556:

> the intent of this type is to only yield the asynchronous task
> responsible for reading the body once. depending on what the inner
> body yields, and when, this can result in combinations of: no data
> frames and no trailers, no data frames with trailers, one data frame
> and no trailers, one data frame with trailers, or two data frames.
> moreover, depending on which of these are yielded, the body will call
> .await some scenarios, and only poll functions once in others.
>
> migrating this to the Frame<T> and poll_frame() style of the 1.0 Body
> interface, away from the 0.4 interface that provides distinct
> poll_data() and poll_trailers() methods, is fundamentally tricky.

this means that `PeekTrailersBody<B>` is notably difficult to port
across the http-body 0.4/1.0 upgrade boundary.

this body middleware must navigate a number of edge conditions, and once
it _has_ obtained a `Frame<T>`, make use of conversion methods to
ascertain whether it is a data or trailers frame, due to the fact that
its internal enum representation is not exposed publicly. one it has
done all of that, it must do the same thing once more to examine the
second frame.

this commit uses the compatibility facilities and backported `Frame<T>`
introduced in the previous commit, and rewrites this control flow using
a form of the `BodyExt::frame()` combinator.

this means that this middleware is forward-compatible with http-body
1.0, which will dramatically simplify the remaining migration work to be
done in #3504.

see https://github.com/linkerd/linkerd2/issues/8733 for more information
and other links related to this ongoing migration work.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): mock body enforces `poll_trailers()` contract

this commit addresses a `TODO` note, and tightens the enforcement of a
rule defined by the v0.4 signature of the `Body` trait.

this commit changes the mock body type, used in tests, so that it will
panic if the caller improperly polls for a trailers frame before the
final data frame has been yielded.

previously, a comment indicated that we were "fairly sure" this was
okay. while that may have been acceptable in practice, the changes in
the previous commit mean that we now properly respect these rules.

thus, a panic can be placed here, to enforce that "[is] only be called
once `poll_data()` returns `None`", per the documentation.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): rename `PeekTrailersBody::Buffered`

<https://github.com/linkerd/linkerd2-proxy/pull/3559#discussion_r1928953710>

this is a nicer name than `Unknown` for this case. not to mention, we'll
want that name shortly to address the possibility of unknown frame
variants.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): encapsulate `Inner<B>` enum variants

this commit makes the inner enum variants private.

https://github.com/linkerd/linkerd2-proxy/pull/3559#discussion_r1928946521

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/retry): gracefully ignore unknown frames

https://github.com/linkerd/linkerd2-proxy/pull/3559#discussion_r1928963019

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-24 15:40:00 -05:00
dependabot[bot] 5d4314c8f6
build(deps): bump codecov/codecov-action from 5.2.0 to 5.3.0 (#3563)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](5a605bd927...0da7aa657d)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-24 12:08:59 -05:00
Zahari Dichev 3ab83ed3ff
feat(metrics)!: remove authority label on inbound metrics (#3547)
The `authority` label is influenced by `:authority` headers and can therefore
can substantially grow in cardinality, depending on traffic patterns.

This change completely removes the authority label from inbound metrics.

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2025-01-24 08:50:55 -08:00
dependabot[bot] 1b5f7faac4
build(deps): bump unicode-ident from 1.0.14 to 1.0.15 (#3562)
Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/dtolnay/unicode-ident/releases)
- [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.14...1.0.15)

---
updated-dependencies:
- dependency-name: unicode-ident
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-24 11:38:46 -05:00
dependabot[bot] e0f9d4519e
build(deps): bump codecov/codecov-action from 5.1.2 to 5.2.0 (#3560)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.1.2 to 5.2.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](1e68e06f1d...5a605bd927)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-23 12:54:52 -05:00
katelyn martin 907f895a8e
fix(http/retry): `is_end_stream()` is true for empty bodies (#3558)
this commit fixes a small, subtle bug in `PeekTrailersBody<B>`.

if wrapping an empty body, the peek body will inspect the wrong
`Option<T>` in the trailers field with the following type:

```rust
    /// The inner body's trailers, if it was terminated by a `TRAILERS` frame
    /// after 0-1 DATA frames, or an error if polling for trailers failed.
    ///
    /// Yes, this is a bit of a complex type, so let's break it down:
    /// - the outer `Option` indicates whether any trailers were received by
    ///   `WithTrailers`; if it's `None`, then we don't *know* if the response
    ///   had trailers, as it is not yet complete.
    /// - the inner `Result` and `Option` are the `Result` and `Option` returned
    ///   by `HttpBody::trailers` on the inner body. If this is `Ok(None)`, then
    ///   the body has terminated without trailers --- it is *known* to not have
    ///   trailers.
    trailers: Option<Result<Option<http::HeaderMap>, B::Error>>,
```

for an empty body, we *know* that there are no trailers, which means
that we have `Some(Ok(None))`.

consider also, the documentation of `is_end_stream()`:

> An end of stream means that both poll_data and poll_trailers will
> return None.
>
> A return value of false does not guarantee that a value will be
> returned from poll_stream or poll_trailers.

we can guarantee in this case that `poll_trailers()` will return
`Ok(None)` since we've already called it and proven that to be the case.
we *are* holding that value, after all.

this change will not affect any behavior w.r.t. what the peek body
yields, but it will mean that it reports `is_end_stream()` correctly
when it wraps an empty body.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-22 15:24:42 -05:00
Scott Fleener 4f0775d539
build(rustls): Upgrade tokio-rustls to 0.26 (#3557)
* Revert "Revert "chore(deps): Upgrade tokio-rustls to 0.26 (#3419)""

This reverts commit de25333e23.

* Expand the set of supported signature algorithms

During the rustls upgrade, it accidentally limited the set of supported signature algorithms to ECDSA256 signatures. This would cause the identity control plane proxy to reject all certify requests with BadSignature if an RSA certificate was used instead of ECDSA.

This updates the set of supported algorithms to most of the full set of what rustls+ring supports, minus a few legacy algorithms.

Tested by deploying to a local cluster and verifying the control plane comes up correctly and app-level networking works as expected.

Signed-off-by: Scott Fleener <scott@buoyant.io>

---------

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-01-22 14:07:18 -05:00
katelyn martin 399ab1dca4 feat(http/retry): unit test suite for `PeekTrailersBody<B>`
`PeekTrailersBody<B>` contains some subtle edge cases related to the
number of DATA frames yielded by the inner body, and how persistent it
will be about polling for TRAILERS frames.

for example, if it yields a DATA frame, it will not await trailers being
available, but it *will* do so if the inner body does not yield a DATA
frame. if a DATA frame is yielded, it will check for a TRAILERS frame,
but it must be immmediately available.

this is all subtle, and particularly subject to change with the upgrade
to http-body 1.0's frame-oriented `Body` interface.

so, this commit introduces a test suite for `PeekTrailersBody<B>`. it
includes assertions to confirm when the peek middleware can and cannot
observe the trailers.

some `TODO(kate)` comments are left where issues exist.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-22 12:56:32 -05:00
katelyn martin 05e71c9215 refactor(http/retry): refactor `PeekTrailersBody<B>` logic
this is a squashed commit containing the following:

---

refactor(http/retry): decompose `WithPeekTrailersBody<B>` type alias

this commit breaks this large type out into two halves.

this is a purely cosmetic change.

Signed-off-by: katelyn martin <kate@buoyant.io>

refactor(http/retry): `PeekTrailersBody` is pin projected

we must pass our `Pin<T>`'edness down to the inner `B`-typed body for
`PeekTrailersBody` to itself implement `http_body::Body`.

this commit tweaks the existing code to rely on the `pin-project`
library. this generates a `project()` method to pin inner fields whose
`poll_data()` and `poll_trailers()` functions we delegate to.

this is a noöp change.

Signed-off-by: katelyn martin <kate@buoyant.io>

refactor(http/retry): defer construction of `PeekTrailersBody<B>`

this commit refactors the polling logic in
`PeekTrailersBody<B>::read_response`.

this commit makes some subtle changes with the migration to hyper 1.0 in
mind, to make this function more easily portable to the new signature of
`http_body::Body`.

see https://github.com/linkerd/linkerd2/issues/8733 for more
information.

this commit defers the `Self` construction of the `PeekTrailersBody`
body. this means that the control flow does not need to reach through to
e.g. `body.inner` to poll the inner body being peeked. additionally, it
provides us with `let` bindings for the first data frame yielded, and
the trailers frame yielded thereafter.

this is largely cosmetic, but will make it easier to deal with the
additional matching we'll need to do when there is a single polling
function that yields us `Frame<D>` objects.

Signed-off-by: katelyn martin <kate@buoyant.io>

refactor(http/retry): `PeekTrailersBody` transforms `B`

this is a small structural change to the
`PeekTrailersBody::read_response()` function to facilitate writing some
unit tests.

rather than transforming a `Response<B>` into a
`Response<PeekTrailersBody<B>>`, we hoist the `Response::into_parts()`
and `Response::from_parts()` calls up. `read_response()` is renamed to
`read_body()`.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-22 12:56:32 -05:00
katelyn martin de0317c79c docs(http/retry): document `PeekTrailersBody<B>` interfaces
this is a squashed commit containing the following:

---

docs(http/retry): document `PeekTrailersBody::inner`

Signed-off-by: katelyn martin <kate@buoyant.io>

docs(http/retry): document `PeekTrailersBody::peek_trailers()`

Signed-off-by: katelyn martin <kate@buoyant.io>

docs(http/retry): document `PeekTrailersBody::no_trailers()`

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-22 12:56:32 -05:00
katelyn martin 76b5f10a9e
refactor(http/upgrade): `Http11Upgrade` is `Clone` (#3540)
* refactor(http/upgrade): `Http11Upgrade::insert_half` matches on `self`

this is a noöp change, to set the stage for subsequent changes to the
internal model of `Http11Upgrade`.

this `inner` field will shortly be an option, and this will make it
easier to only follow these panicking branches when the inner lock is
`Some(_)`.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/upgrade): `Http11Upgade` stores an `Option<T>`

this commit hinges on this change to the upgrade middleware's `inner`
field.

we still retain a reference-counted copy of the `Inner` state, but now
we may store `None` here.

```
 pub struct Http11Upgrade {
     half: Half,
-    inner: Arc<Inner>,
+    inner: Option<Arc<Inner>>,
 }
```

a new branch is added to the `insert_half` method that consumes the
"sender" and inserts an upgrade future; when this is `None` it will do
nothing, rather than panicking.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/upgrade): `Half` marker is `Copy`

this type is an empty flag to indicate whether an `Http11Upgrade`
extension corresponds to the server or client half of the upgrade
future channel.

this type is made copy, to facilitate making the `Http11Upgrade`
extension safely cloneable.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/upgrade): `Http11Upgrade` is `Clone`

this commit makes `Http11Upgrade` a cloneable type.

see <https://github.com/linkerd/linkerd2/issues/8733>.

in the 1.0 interface of the `http` crate, request and response
extensions must now satisfy a `Clone` bound.

`Http11Upgrade` was written before this was the case, and is very
intentionally designed around the idea that it *not* be cloneable.

`insert_half()` in particular could cause the proxy to panic if it were
to clone a request or response's extensions. it might call
`insert_half()` a second time, and discover that the `TryLock<T>` had
already been set.

moreover, holding on to a copy of the extensions would prevent the
`Drop` method for `Inner` from being called. This would cause
connections that negotiate an HTTP/1.1 upgrade to deadlock due to the
`OnUpgrade` futures never being polled, and failing to create a `Duplex`
that acts as the connection's I/O transport.

this commit makes use of the alterations to `Http11Upgrade` made in
previous commits, and adds a *safe* implementation of `Clone`. by
only shallowly copying the extension, we tie the upgrade glue to a
*specific* request/response.

the extension can be cloned, but any generated copies will be inert.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/upgrade): fix broken intradoc links

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(http/upgrade): add `thiserror` dependency

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(proxy/http): use `.await` syntax

`FutureExt::map_ok()` won't work if we try to return an error from this
block. the `and_then()` adaptor is used to chain futures, and also won't
work given a synchronous closure.

this can be done with the equivalent `.await` syntax, and leaves a nicer
hole for us to propagate other errors here, shortly.

Signed-off-by: katelyn martin <kate@buoyant.io>

* review(http/upgrade): propagate `insert_half()` failures

https://github.com/linkerd/linkerd2-proxy/pull/3540#discussion_r1924496977

Signed-off-by: katelyn martin <kate@buoyant.io>
Co-Authored-By: Oliver Gould <ver@buoyant.io>

* docs(http/upgrade): tweak comment

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-01-22 12:24:30 -05:00
dependabot[bot] b8d29a2fc6
build(deps): bump rustix from 0.38.42 to 0.38.44 (#3554)
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.42 to 0.38.44.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.42...v0.38.44)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-22 11:04:03 -05:00
Oliver Gould d436b93d23
chore(http): rename http/version to http/variant (#3555)
The proxy::http::Version type is very similar to the HTTP crate's Version type,
though it is more constrained so that the proxy may exhaustively match on it.
This change renames the module to http::variant to avoid confusion with the HTTP
crate's Version type.

To disambiguate the HTTP version type, the proxy::http::Version type is renamed
to proxy::http::Variant.
2025-01-22 07:55:48 -08:00
Scott Fleener de25333e23 Revert "chore(deps): Upgrade tokio-rustls to 0.26 (#3419)"
This reverts commit bb6e9b7f94.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-01-21 16:27:37 -05:00
dependabot[bot] cfc0de7ab6
build(deps): bump symbolic-common from 12.13.2 to 12.13.3 (#3552)
Bumps [symbolic-common](https://github.com/getsentry/symbolic) from 12.13.2 to 12.13.3.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.13.2...12.13.3)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 11:08:22 -05:00
dependabot[bot] af7cdf024f
build(deps): bump semver from 1.0.24 to 1.0.25 (#3551)
Bumps [semver](https://github.com/dtolnay/semver) from 1.0.24 to 1.0.25.
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.24...1.0.25)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 11:08:11 -05:00
dependabot[bot] d5a78f7dbb
build(deps): bump serde_json from 1.0.135 to 1.0.137 (#3550)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.135 to 1.0.137.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.135...v1.0.137)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 11:08:01 -05:00
dependabot[bot] 965aacbbae
build(deps): bump symbolic-demangle from 12.13.1 to 12.13.3 (#3549)
Bumps [symbolic-demangle](https://github.com/getsentry/symbolic) from 12.13.1 to 12.13.3.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.13.1...12.13.3)

---
updated-dependencies:
- dependency-name: symbolic-demangle
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 11:07:47 -05:00
dependabot[bot] 0dddce63b9
build(deps): bump uuid from 1.12.0 to 1.12.1 (#3548)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.12.0 to 1.12.1.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/1.12.0...1.12.1)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 11:07:37 -05:00
dependabot[bot] 52cc6cca7a
build(deps): bump valuable from 0.1.0 to 0.1.1 (#3545)
Bumps [valuable](https://github.com/tokio-rs/valuable) from 0.1.0 to 0.1.1.
- [Release notes](https://github.com/tokio-rs/valuable/releases)
- [Changelog](https://github.com/tokio-rs/valuable/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/valuable/compare/v0.1.0...v0.1.1)

---
updated-dependencies:
- dependency-name: valuable
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 07:06:36 -08:00
dependabot[bot] ecb9ae9cb5
build(deps): bump DavidAnson/markdownlint-cli2-action (#3542)
Bumps [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action) from 19.0.0 to 19.1.0.
- [Release notes](https://github.com/davidanson/markdownlint-cli2-action/releases)
- [Commits](a23dae216c...05f32210e8)

---
updated-dependencies:
- dependency-name: DavidAnson/markdownlint-cli2-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 07:06:23 -08:00
dependabot[bot] b9247687c1
build(deps): bump prettyplease from 0.2.25 to 0.2.29 (#3544)
Bumps [prettyplease](https://github.com/dtolnay/prettyplease) from 0.2.25 to 0.2.29.
- [Release notes](https://github.com/dtolnay/prettyplease/releases)
- [Commits](https://github.com/dtolnay/prettyplease/compare/0.2.25...0.2.29)

---
updated-dependencies:
- dependency-name: prettyplease
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 07:05:04 -08:00
dependabot[bot] 4d6077c097
build(deps): bump indexmap from 2.7.0 to 2.7.1 (#3543)
Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.7.0 to 2.7.1.
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/master/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.7.0...2.7.1)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 07:04:45 -08:00
dependabot[bot] 57b25b5f60
build(deps): bump ipnet from 2.10.1 to 2.11.0 (#3546)
Bumps [ipnet](https://github.com/krisprice/ipnet) from 2.10.1 to 2.11.0.
- [Release notes](https://github.com/krisprice/ipnet/releases)
- [Changelog](https://github.com/krisprice/ipnet/blob/master/RELEASES.md)
- [Commits](https://github.com/krisprice/ipnet/commits/2.11.0)

---
updated-dependencies:
- dependency-name: ipnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 07:04:31 -08:00
dependabot[bot] 46d39ffec3
build(deps): bump data-encoding from 2.6.0 to 2.7.0 (#3533)
Bumps [data-encoding](https://github.com/ia0/data-encoding) from 2.6.0 to 2.7.0.
- [Commits](https://github.com/ia0/data-encoding/commits)

---
updated-dependencies:
- dependency-name: data-encoding
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-17 15:56:28 -05:00
dependabot[bot] 07ae3a07b8
build(deps): bump log from 0.4.22 to 0.4.25 (#3536)
Bumps [log](https://github.com/rust-lang/log) from 0.4.22 to 0.4.25.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.22...0.4.25)

---
updated-dependencies:
- dependency-name: log
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-17 15:56:02 -05:00
dependabot[bot] 16ea024c55
build(deps): bump uuid from 1.11.0 to 1.12.0 (#3534)
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/1.11.0...1.12.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-17 15:55:47 -05:00
dependabot[bot] 435cce6f97
build(deps): bump cc from 1.2.7 to 1.2.10 (#3539)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.7 to 1.2.10.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.7...cc-v1.2.10)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-17 15:17:21 -05:00
katelyn martin 10bb2852fc
refactor(http/retry): remove unused `ResponseWithPeekTrailers<S>` (#3541)
`ResponseWithPeekTrailers` wraps an inner service `S`.

upon inspection, it turns out that this structure is no longer used by
any code elsewhere in the project.

this commit removes `ResponseWithPeekTrailers`, its associated type
aliases, and its `tower::Service<T>` implementation.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-17 15:12:01 -05:00
Zahari Dichev 329bee2b3b
transport: fix wrong type in non-linux orig_dst_* method (#3538)
Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
2025-01-16 19:15:18 +02:00
katelyn martin a4a55fa5fb
docs(http/upgrade): document `linkerd-http-upgrade` (#3531)
some aspects of `linkerd-http-upgrade` are incompatible with the 1.0
interface of the `http` crate (_see: hyperium/http#395,
linkerd/linkerd2#8733_).

this new bound requiring that extensions must now be cloneable motivated
me to read through this library's internals to gain a lucid
understanding of how it works, in order to understand how to gracefully
address
[this](https://github.com/linkerd/linkerd2-proxy/blob/main/linkerd/http/upgrade/src/upgrade.rs#L25-L26)
comment affixed to the `linkerd_http_upgrade::upgrade::Http11Upgrade`
request/response extension:

```rust
// Note: this relies on their only having been 2 Inner clones, so don't
// implement `Clone` for this type. [sic]
pub struct Http11Upgrade {
    half: Half,
    inner: Arc<Inner>,
}
```

broadly, this library deals with some moderately arcane corners of the
HTTP protocol family. the `Upgrade` header is not supported in HTTP/2,
and was not yet introduced in HTTP/1.0, so it is a feature specific to
HTTP/1.1. moreover, some behavior provided by this library falls into
parts of the spec(s) that we `MUST` uphold, and isn't currently well
documented.

this branch includes a sequence of commits adding documentation and
additional comments linking to, and quoting, the relevant parts of [RFC
9110](https://www.rfc-editor.org/rfc/rfc9110). some links to RFC 7231,
which was obsoleted by RFC 9110 since the original time of writing, are
additionally updated.

some comments also did not accurately describe internal logic, or
included typos, and are also updated.

---

* docs(http/upgrade): add crate-level docs, rfc link

Signed-off-by: katelyn martin <kate@buoyant.io>

* docs(http/upgrade): update link to obsolete rfc

rfc 9110 obsoletes the following rfc's: 2818, 7230, 7231, 7232, 7233,
7235, 7538, 7615, and 7694.

this updates a comment related to connection upgrade logic, linking to
the current rfc, 9110. this information now lives in section 9.3.6,
paragraph 12.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(http/upgrade): update incorrect comment

this function has since been renamed `halves()`.

Signed-off-by: katelyn martin <kate@buoyant.io>

* docs(http/upgrade): add comments to `wants_upgrade`

this adds a comment additionally clarifying that HTTP/2 does not support
upgrades.

Signed-off-by: katelyn martin <kate@buoyant.io>

* docs(http/upgrade): document `strip_connection_headers()`

this function performs some important behavior that we MUST implement,
as a proxy/intermediary.

to help elucidate the mandated behavior expected of us by the HTTP/1
specification, add documentation comments noting the related passages
from rfc 9110 § 7.6.1.

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(http/upgrade): fix typo in `Http11Upgrade` comment

Signed-off-by: katelyn martin <kate@buoyant.io>

* docs(http/upgrade): update incorrect comment

this comment is not true.

this commit updates it, reflecting the current state of the upgrade
body's `Drop` logic.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-16 10:36:13 -05:00
katelyn martin fed1e89a01
refactor(http/upgrade): internal interfaces are private (#3530)
the `linkerd-http-upgrade` crate supports HTTP/1.1 upgrades. currently, it
exposes a number of functions and types in its public interface that are
strictly internal helpers. this branch redefines various interfaces and fields
as private, to clarify the public interface of the crate.

---

* refactor(proxy/http): `h1::is_upgrade()` is private

this function is not used elsewhere, so it does not have to be
`pub(crate)`.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/upgrade): `halves()` is private

this commit restricts `Http11Upgrade::halves` so that it is now a
private interface.

this is an internal interface that is not used elsewhere.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/upgrade): `Http11UpgradeHalves` is private

with `halves()` having been made private, this type is also not used by
other external code. we can make it, and its constituent fields,
private.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/upgrade): `UpgradeBody::upgrade` is private

this commit makes the `upgrade` field of the `UpgradeBody` type private.
it contains two pieces of state that are used in the `Drop`
implementation of an upgrade body.

because these are not accessed or modified elsewhere, this field can be
made private.

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(http/upgrade): `UpgradeBody::new` is `pub(crate)`

this function is not, and *should* not, be used by external callers. we
install the `UpgradeBody` in `Service`.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-15 12:53:08 -05:00
dependabot[bot] 7b2fd18c51
build(deps): bump symbolic-common from 12.13.1 to 12.13.2 (#3529)
Bumps [symbolic-common](https://github.com/getsentry/symbolic) from 12.13.1 to 12.13.2.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.13.1...12.13.2)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 06:00:48 -08:00
dependabot[bot] a0a3c40e98
build(deps): bump proc-macro2 from 1.0.92 to 1.0.93 (#3525)
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.92 to 1.0.93.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.92...1.0.93)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 06:00:30 -08:00
dependabot[bot] 9608e2c516
build(deps): bump simple_asn1 from 0.6.2 to 0.6.3 (#3527)
Bumps [simple_asn1](https://github.com/acw/simple_asn1) from 0.6.2 to 0.6.3.
- [Commits](https://github.com/acw/simple_asn1/commits)

---
updated-dependencies:
- dependency-name: simple_asn1
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 06:00:11 -08:00
dependabot[bot] dc0ca33cbe
build(deps): bump tokio from 1.42.0 to 1.43.0 (#3526)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.42.0 to 1.43.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.42.0...tokio-1.43.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 05:59:52 -08:00
dependabot[bot] d7c7913b40
build(deps): bump syn from 2.0.95 to 2.0.96 (#3524)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.95 to 2.0.96.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.95...2.0.96)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 10:29:02 -05:00
dependabot[bot] 5af46e82ea
build(deps): bump linux-raw-sys from 0.4.14 to 0.4.15 (#3521)
Bumps [linux-raw-sys](https://github.com/sunfishcode/linux-raw-sys) from 0.4.14 to 0.4.15.
- [Commits](https://github.com/sunfishcode/linux-raw-sys/compare/v0.4.14...v0.4.15)

---
updated-dependencies:
- dependency-name: linux-raw-sys
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 05:27:51 -08:00
dependabot[bot] bd4b0698bf
build(deps): bump thiserror from 2.0.10 to 2.0.11 (#3523)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.10 to 2.0.11.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.10...2.0.11)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 05:27:13 -08:00
dependabot[bot] 6a95fb6add
build(deps): bump rustls from 0.23.20 to 0.23.21 (#3522)
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.20 to 0.23.21.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.20...v/0.23.21)

---
updated-dependencies:
- dependency-name: rustls
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 05:26:58 -08:00
katelyn martin e133da1813
chore(http/retry): use boxed bodies instead of `hyper::Body` (#3515)
see #8733.

the tests for the replay body use the `hyper::Body` type removed in the
1.0 release.

this commit replaces this with `BoxBody` where possible, and adds
comments with context about how to update code once upgrading to hyper
1.0.

see #3467 and #3468 which added `from_static()` and `empty()`,
respectively.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-10 11:19:57 -05:00
dependabot[bot] ef4bc91597
build(deps): bump serde_json from 1.0.133 to 1.0.135 (#3520)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.133 to 1.0.135.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.133...v1.0.135)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 09:58:09 -05:00
dependabot[bot] 7d077304c5
build(deps): bump symbolic-demangle from 12.12.4 to 12.13.1 (#3519)
Bumps [symbolic-demangle](https://github.com/getsentry/symbolic) from 12.12.4 to 12.13.1.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.12.4...12.13.1)

---
updated-dependencies:
- dependency-name: symbolic-demangle
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 09:57:59 -05:00
dependabot[bot] e58fc17f24
build(deps): bump thiserror from 2.0.9 to 2.0.10 (#3518)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.9 to 2.0.10.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.9...2.0.10)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 09:57:50 -05:00
dependabot[bot] 07229ba1ee
build(deps): bump quote from 1.0.37 to 1.0.38 (#3517)
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.37 to 1.0.38.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.37...1.0.38)

---
updated-dependencies:
- dependency-name: quote
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 09:57:43 -05:00
dependabot[bot] 406784f23f
build(deps): bump actions/upload-artifact from 4.5.0 to 4.6.0 (#3516)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](6f51ac03b9...65c4c4a1dd)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 09:57:33 -05:00
dependabot[bot] 8b64841fc1
build(deps): bump pin-project-lite from 0.2.15 to 0.2.16 (#3514)
Bumps [pin-project-lite](https://github.com/taiki-e/pin-project-lite) from 0.2.15 to 0.2.16.
- [Release notes](https://github.com/taiki-e/pin-project-lite/releases)
- [Changelog](https://github.com/taiki-e/pin-project-lite/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project-lite/compare/v0.2.15...v0.2.16)

---
updated-dependencies:
- dependency-name: pin-project-lite
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 14:43:36 -05:00
dependabot[bot] c8ba4f7dd1
build(deps): bump thiserror from 2.0.8 to 2.0.9 (#3513)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.8 to 2.0.9.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.8...2.0.9)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 14:43:21 -05:00
dependabot[bot] 9f57bfe161
build(deps): bump serde from 1.0.216 to 1.0.217 (#3512)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.216 to 1.0.217.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.216...v1.0.217)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 14:43:07 -05:00
dependabot[bot] 5be73b04a7
build(deps): bump async-trait from 0.1.84 to 0.1.85 (#3511)
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.84 to 0.1.85.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.84...0.1.85)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 14:42:58 -05:00
dependabot[bot] 4a5cf9c8cc
build(deps): bump softprops/action-gh-release from 2.2.0 to 2.2.1 (#3510)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.2.0 to 2.2.1.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](7b4da11513...c95fe14893)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 14:42:50 -05:00
dependabot[bot] aeea13307b
build(deps): bump tempfile from 3.14.0 to 3.15.0 (#3505)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.14.0 to 3.15.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.14.0...v3.15.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 10:37:02 -05:00
dependabot[bot] 4c3c46e142
build(deps): bump rustversion from 1.0.18 to 1.0.19 (#3507)
Bumps [rustversion](https://github.com/dtolnay/rustversion) from 1.0.18 to 1.0.19.
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.18...1.0.19)

---
updated-dependencies:
- dependency-name: rustversion
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 10:36:49 -05:00
dependabot[bot] 0b7de7d0de
build(deps): bump pin-project from 1.1.7 to 1.1.8 (#3508)
Bumps [pin-project](https://github.com/taiki-e/pin-project) from 1.1.7 to 1.1.8.
- [Release notes](https://github.com/taiki-e/pin-project/releases)
- [Changelog](https://github.com/taiki-e/pin-project/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/pin-project/compare/v1.1.7...v1.1.8)

---
updated-dependencies:
- dependency-name: pin-project
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 10:36:21 -05:00
dependabot[bot] c869d2c16a
build(deps): bump rcgen from 0.12.1 to 0.13.2 (#3485)
* build(deps): bump rcgen from 0.12.1 to 0.13.2

Bumps [rcgen](https://github.com/rustls/rcgen) from 0.12.1 to 0.13.2.
- [Release notes](https://github.com/rustls/rcgen/releases)
- [Commits](https://github.com/rustls/rcgen/compare/v0.12.1...v0.13.2)

---
updated-dependencies:
- dependency-name: rcgen
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* use new api

Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Zahari Dichev <zaharidichev@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zahari Dichev <zaharidichev@gmail.com>
2025-01-07 14:54:47 +02:00
katelyn martin b07b0d88e3
chore(proxy/http): replace `hyper::Body` with `BoxBody` (#3480)
`UpgradeResponseBody` currently wraps a `hyper::Body`. this type is
removed in hyper 1.0.

this commit replaces this with a generic `B`-typed body.

see https://github.com/linkerd/linkerd2-proxy/pull/3479, which performs
the same change in `linkerd-http-upgrade`.

see https://github.com/linkerd/linkerd2/issues/8733 for more information
on upgrading to hyper 1.0.

Signed-off-by: katelyn martin <kate@buoyant.io>
2025-01-06 13:47:18 -05:00
Oliver Gould 612bf6779d
chore: bump dev from v44 to v45 (#3496)
Updates LLVM from 14 to 19.

We pin ubuntu to 24.04 to ensure compatibility.
2025-01-06 13:27:49 -05:00
Oliver Gould a4f0ab80b3
build(deps): update boring from 3.1.0 to 4.13.0 (#3495) 2025-01-06 12:37:39 -05:00
dependabot[bot] 63937f61f6
build(deps): bump glob from 0.3.1 to 0.3.2 (#3500)
Bumps [glob](https://github.com/rust-lang/glob) from 0.3.1 to 0.3.2.
- [Release notes](https://github.com/rust-lang/glob/releases)
- [Changelog](https://github.com/rust-lang/glob/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/glob/compare/0.3.1...v0.3.2)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-06 14:40:43 +00:00
dependabot[bot] c0c16cc3b2
build(deps): bump tj-actions/changed-files from 45.0.5 to 45.0.6 (#3501)
Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 45.0.5 to 45.0.6.
- [Release notes](https://github.com/tj-actions/changed-files/releases)
- [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md)
- [Commits](bab30c2299...d6e91a2266)

---
updated-dependencies:
- dependency-name: tj-actions/changed-files
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-06 09:34:38 -05:00
dependabot[bot] 57eb4e3105
build(deps): bump syn from 2.0.94 to 2.0.95 (#3499)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.94 to 2.0.95.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.94...2.0.95)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-06 09:34:21 -05:00
dependabot[bot] 1554e9e35a
build(deps): bump cc from 1.2.5 to 1.2.7 (#3498)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.5 to 1.2.7.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.5...cc-v1.2.7)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-06 09:34:11 -05:00
dependabot[bot] c5e3ed04e5
build(deps): bump async-trait from 0.1.83 to 0.1.84 (#3497)
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.83 to 0.1.84.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.83...0.1.84)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-06 09:34:01 -05:00
Scott Fleener 563dd3fd83 Use correct semantic conventions for trace labels
The OpenTelemetry spec defines the semantic conventions that HTTP services should use for the labels included in traces: https://opentelemetry.io/docs/specs/semconv/http/http-spans/

Previously, we were using an outdated version of this spec for the OpenCensus traces. This updates the labels to match the current spec.

The notable changes updates to the path for HTTP method and status code, the fields that include the URL parts, and more rigorously following the standard for propagating the Host header.

Signed-off-by: Scott Fleener <scott@buoyant.io>
2025-01-06 08:45:50 -05:00
katelyn martin 387197e388
chore(hyper): upgrade to hyper 0.14.32 (#3472)
this commit upgrades to hyper 0.14.32, removing the manifest's `[patch]`
section.

hyperium/hyper#3796 backported a method we use when building http/2
connections. #3457 patched the workspace to rely on a git dependency
of hyper at commit `a24f0c0a`.

this work has been released in version 0.14.32.

this commit also changes `deny.toml`, removing the exception we carved
out for hyper in #3457.

for more information, see:

* hyperium/hyper#3796
* linkerd/linkerd2#8733
* https://github.com/hyperium/hyper/commits/0.14.x
* #3457
* 03f55779

Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2025-01-05 19:51:02 +00:00
dependabot[bot] af52f36a63
build(deps): bump anyhow from 1.0.94 to 1.0.95 (#3488)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.94 to 1.0.95.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.94...1.0.95)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-05 17:40:16 +00:00
dependabot[bot] b6dbe72465
build(deps): bump DavidAnson/markdownlint-cli2-action (#3492)
Bumps [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action) from 18.0.0 to 19.0.0.
- [Release notes](https://github.com/davidanson/markdownlint-cli2-action/releases)
- [Commits](eb5ca3ab41...a23dae216c)

---
updated-dependencies:
- dependency-name: DavidAnson/markdownlint-cli2-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-05 09:36:21 -08:00
dependabot[bot] 3b89e60ab3
build(deps): bump syn from 2.0.90 to 2.0.94 (#3494)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.90 to 2.0.94.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.90...2.0.94)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-05 09:36:10 -08:00
dependabot[bot] dbf072e839
build(deps): bump Swatinem/rust-cache from 2.7.5 to 2.7.7 (#3491)
Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.7.5 to 2.7.7.
- [Release notes](https://github.com/swatinem/rust-cache/releases)
- [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md)
- [Commits](82a92a6e8f...f0deed1e0e)

---
updated-dependencies:
- dependency-name: Swatinem/rust-cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-05 09:35:52 -08:00
dependabot[bot] b59014be7e
build(deps): bump tinyvec from 1.8.0 to 1.8.1 (#3489)
Bumps [tinyvec](https://github.com/Lokathor/tinyvec) from 1.8.0 to 1.8.1.
- [Changelog](https://github.com/Lokathor/tinyvec/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Lokathor/tinyvec/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: tinyvec
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-05 09:35:37 -08:00
dependabot[bot] 53b279c29d
build(deps): bump object from 0.36.5 to 0.36.7 (#3486)
Bumps [object](https://github.com/gimli-rs/object) from 0.36.5 to 0.36.7.
- [Changelog](https://github.com/gimli-rs/object/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gimli-rs/object/compare/0.36.5...0.36.7)

---
updated-dependencies:
- dependency-name: object
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-05 09:34:29 -08:00
katelyn martin fcfde84a39
chore(http/upgrade): replace `hyper::Body` with `BoxBody` (#3479)
* chore(http/upgrade): replace `hyper::Body` with `BoxBody`

`hyper::Body` is removed in the 1.0 version.

this commit removes it from our upgrade facilities, using a generic body
parameter that defaults to BoxBody.

see <https://github.com/linkerd/linkerd2/issues/8733>.

Signed-off-by: katelyn martin <kate@buoyant.io>

* review(http/upgrade): remove frivolous `Unpin` bound

https://github.com/linkerd/linkerd2-proxy/pull/3479/files#r1894068885

in `main` this isn't currently pinned, so this was needed to add the `B`
parameter originally in development, but tweaking how we poll the body
(_see lines 70-80, below_) means this bound is indeed frivolous now.

this commit removes an extraneous `Unpin` bound.

Co-authored-by: Scott Fleener <scott@buoyant.io>
Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: Scott Fleener <scott@buoyant.io>
2024-12-20 11:53:07 -05:00
katelyn martin 81b43e5633
refactor(app/core): build.rs prints invalid proxy version (#3482)
if this build script panics due to an invalid proxy version environment
variable, the panic can be somewhat cryptic. a message saying
`LINKERD2_PROXY_VERSION must be semver` is printed, but the proxy
version that caused this is not shown.

this commit adds the version and the error to this panic message.

now, building with an invalid proxy version provides us with the
following:

```
; LINKERD2_PROXY_VERSION='invalid' cargo build -p linkerd-app-core
   Compiling linkerd-app-core v0.1.0 (/linkerd2-proxy/linkerd/app/core)
error: failed to run custom build command for `linkerd-app-core v0.1.0 (/linkerd2-proxy/linkerd/app/core)`
note: To improve backtraces for build dependencies, set the CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG=true environment variable to enable debug information generation.

Caused by:
  process didn't exit successfully: `/linkerd2-proxy/target/debug/build/linkerd-app-core-756fc82028bfbcc0/build-script-build` (exit status: 101)
  --- stdout
  cargo:rustc-env=GIT_SHA=e53b6b9d

  cargo:rustc-env=LINKERD2_PROXY_BUILD_DATE=2024-12-20T01:18:08Z

  --- stderr
  thread 'main' panicked at linkerd/app/core/build.rs:18:17:
  LINKERD2_PROXY_VERSION must be semver: version='invalid' error='unexpected character 'i' while parsing major version number'
```

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-20 11:18:39 -05:00
katelyn martin a1a57139b1 refactor(deps): define `linkerd2-proxy-api` using table (#3473)
this is a small cosmetic tweak to the cargo workspace manifest.

this defines the proxy api as a toml table, to help give us a more
natural place to hang the (inert) example of a git dependency used in
development.

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-19 14:20:52 -05:00
katelyn martin 2fe2321743 chore(deps): define h2 as a workspace dependency (#3473)
this commit modifies the workspace manifest, defining h2 as a
workspace dependency.

no changes to the lockfile are made because this commit does not affect
the dependency graph of the project.

* linkerd/linkerd2#8733

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-19 14:20:52 -05:00
katelyn martin 0ff60aa1cb chore(deps): define bytes as a workspace dependency (#3473)
this commit modifies the workspace manifest, defining bytes as a
workspace dependency.

no changes to the lockfile are made because this commit does not affect
the dependency graph of the project.

* linkerd/linkerd2#8733

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-19 14:20:52 -05:00
katelyn martin 5687faa6cf chore(deps): define tonic, tonic-build as workspace dependencies (#3473)
this commit modifies the workspace manifest, defining tonic and
tonic-build as common workspace dependencies.

no changes to the lockfile are made because this commit does not affect
the dependency graph of the project.

* linkerd/linkerd2#8733

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-19 14:20:52 -05:00
katelyn martin b87455a9f7 chore(deps): define prost, prost-types as workspace dependencies (#3473)
this commit modifies the workspace manifest, defining prost and
prost-types as common workspace dependencies.

no changes to the lockfile are made because this commit does not affect
the dependency graph of the project.

* linkerd/linkerd2#8733

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-19 14:20:52 -05:00
dependabot[bot] 8fd2e7261c
build(deps): bump codecov/codecov-action from 5.1.1 to 5.1.2 (#3474)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.1.1 to 5.1.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](7f8b4b4bde...1e68e06f1d)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 12:52:09 -05:00
dependabot[bot] dad2aa98b2
build(deps): bump cc from 1.2.4 to 1.2.5 (#3475)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.4 to 1.2.5.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.4...cc-v1.2.5)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 12:51:58 -05:00
dependabot[bot] 9b6c1b962d
build(deps): bump symbolic-demangle from 12.12.3 to 12.12.4 (#3476)
Bumps [symbolic-demangle](https://github.com/getsentry/symbolic) from 12.12.3 to 12.12.4.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.12.3...12.12.4)

---
updated-dependencies:
- dependency-name: symbolic-demangle
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 12:51:47 -05:00
dependabot[bot] 3390e1f628
build(deps): bump libc from 0.2.168 to 0.2.169 (#3477)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.168 to 0.2.169.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.169/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.168...0.2.169)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 12:51:33 -05:00
dependabot[bot] 9d0124be32
build(deps): bump symbolic-common from 12.12.3 to 12.12.4 (#3478)
Bumps [symbolic-common](https://github.com/getsentry/symbolic) from 12.12.3 to 12.12.4.
- [Release notes](https://github.com/getsentry/symbolic/releases)
- [Changelog](https://github.com/getsentry/symbolic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/symbolic/compare/12.12.3...12.12.4)

---
updated-dependencies:
- dependency-name: symbolic-common
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 12:51:24 -05:00
dependabot[bot] 17e52f9645
build(deps): bump actions/upload-artifact from 4.4.3 to 4.5.0 (#3471)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.3 to 4.5.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](b4b15b8c7c...6f51ac03b9)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-18 15:09:13 -05:00
dependabot[bot] 20d5dd9f03
build(deps): bump thiserror from 2.0.7 to 2.0.8 (#3470)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.7 to 2.0.8.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.7...2.0.8)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-18 14:26:45 -05:00
katelyn martin deb92db9e3
refactor: move away from legacy `hyper::body::HttpBody` (#3467)
* refactor: move away from legacy `hyper::body::HttpBody`

this is an incremental step away from hyper 0.14's request and response
body interfaces, and towards the 1.0 body types. see
<https://github.com/linkerd/linkerd2/issues/8733> for more information
about upgrading to hyper 1.0.

hyper 0.14 provides a `hyper::body::Body` that is removed in the 1.0
interface. `hyper-util` now provides a workable default body type. hyper
0.14 reëxports `http_body::Body` as `HttpBody`. hyper 1.0 reëxports this
trait as `hyper::body::Body` without any renaming.

this commit moves application code away from hyper's legacy `Body` type
and the `HttpBody` trait alias. this commit moves assorted interfaces
towards the boxed `BoxBody` type instead. when possible, code is tweaked
such that it refers to the reëxport in `linkerd-proxy-http`, rather than
directly through `hyper`.

NB: this commit is based upon #3466.

Signed-off-by: katelyn martin <kate@buoyant.io>

* feat(http/box): `BoxBody::from_static` constructor

this commit relates to review feedback offered here:
https://github.com/linkerd/linkerd2-proxy/pull/3467#discussion_r1888979001

it is slightly ungainly to place a static string into a BoxBody,
something that is a fairly common pattern throughout e.g. our admin
server.

to help nudge the compiler to infer a `B: Body` of `String`, various
code follows a common convention of calling e.g.
`BoxBody:🆕:<String>("ready\n".into())` or,
`BoxBody::new("ready\n".to_string())`.

this commit helps reduce that boilerplate by adding a `from_static(..)`
constructor that accepts a static string.

```rust
    /// Returns a [`BoxBody`] with the contents of a static string.
    pub fn from_static(body: &'static str) -> Self {
        Self::new(body.to_string())
    }
```

Co-authored-by: Scott Fleener <scott@buoyant.io>
Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/admin): outline json bytes body construction

see <https://github.com/linkerd/linkerd2-proxy/pull/3467#discussion_r1888980453>.

@sfleen points out this unfortunate part of our diff:

```diff
-           .body(json.into())
+           .body(BoxBody::new(http_body::Full::new(bytes::Bytes::from(json))))
```

this *is* a bit of an unfortunate edge, where boxing up a body feels
especially cumbersome.

this commit takes an attempt at tweaking the function in question so
that this large nested expression reads a bit nicer.

first, to justify why this gets a little more involved: hyper will no
longer provide the `Body` type after 1.0, so we are tasked with
providing our own body. for our purposes, `Full` works because we have a
single chunk of bytes in hand.

in order to create a `Full`, we must provide a `D: Buf`, which can be
satisfied by the following types:
<https://docs.rs/bytes/1.6.0/bytes/buf/trait.Buf.html#foreign-impls>

most simply, we can cast our vector of bytes into a `Bytes`.

with all of this in hand, we can hoist this creation of the body up out
of the `match` arm, and use `Result::map` to apply these constructors in
sequential order:

```rust
    // Serialize the value into JSON, and then place the bytes in a boxed response body.
    let json = serde_json::to_vec(val)
        .map(Bytes::from)
        .map(http_body::Full::new)
        .map(BoxBody::new);
```

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
Co-authored-by: Scott Fleener <scott@buoyant.io>
2024-12-17 14:53:17 -05:00
katelyn martin 35e7316f10
feat(http/box): `BoxBody::empty()` creates an empty body (#3468)
hyper 0.14's body type provides an `empty()` method that can be used to
construct an empty request or response body.

this commit proposes an equivalent method for `BoxBody`. while it is
semantically equivalent to `BoxBody::default()`, it can be helpful to
clarify that this constructs an empty body.

<https://docs.rs/hyper/0.14.31/hyper/body/struct.Body.html#method.empty>

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-17 13:27:30 -05:00
katelyn martin ca50d6bb75
chore(cargo.toml): define http, http-body as a workspace dependencies (#3466)
this is a follow-up to #3456, addressing a suggestion that was made
during review:

- <https://github.com/linkerd/linkerd2-proxy/pull/3456#pullrequestreview-2502446232>
- <https://github.com/linkerd/linkerd2/issues/8733>

this commit modifies the workspace manifest, defining http and http-body
as common workspace dependencies.

no changes to the lockfile are made because this commit does not affect
the dependency graph of the project.

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-17 07:46:01 -05:00
katelyn martin 7bbfc8ec46
docs(app/test): fix unresolved `SendRequest` links (#3465)
this commit fixes some warnings that are currently present in `main`
when building the project's docs, by mending two broken doc links.

see:
- 42fe4cf66
- <https://github.com/linkerd/linkerd2/issues/8733>

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-16 10:10:20 -05:00
dependabot[bot] 489e1e4faa
build(deps): bump rustls-pki-types from 1.10.0 to 1.10.1 (#3464)
Bumps [rustls-pki-types](https://github.com/rustls/pki-types) from 1.10.0 to 1.10.1.
- [Release notes](https://github.com/rustls/pki-types/releases)
- [Commits](https://github.com/rustls/pki-types/compare/v/1.10.0...v/1.10.1)

---
updated-dependencies:
- dependency-name: rustls-pki-types
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 07:01:11 -08:00
dependabot[bot] 9a143c0ce7
build(deps): bump cc from 1.2.3 to 1.2.4 (#3462)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.3...cc-v1.2.4)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 09:32:22 -05:00
dependabot[bot] 752d14319e
build(deps): bump thiserror from 2.0.6 to 2.0.7 (#3463)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.6...2.0.7)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 09:32:03 -05:00
katelyn martin ea5136268d
chore(proxy/http): address hyper deprecations in `ServeHttp<N>` (#3459)
see linkerd/linkerd2#8733 for more information on upgrading to hyper 1.0.

this commit is based upon #3456, and #3457.

this commit is also contingent upon hyperium/hyper#3796, which backports
the server connection builder's `max_pending_accept_reset_streams()`
method.

this commit addresses hyper deprecations in `ServeHttp<N>`, which
defines a reusable HTTP/1 and HTTP/2 server for the linkerd proxy.

essentially, this commit replaces the singular `Http<E>` with a pair of
http/1 and http/2 specific connection `Builder`s. method names no longer
have `http2_*` prefixes, otherwise nothing about the connection setup
has been changed. in the `Service` implementation, we delegate to the
appropriate builder based upon the protocol version.

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-13 16:54:40 +00:00
katelyn martin f2ad745200
chore(ci): remove duplicate `connect_and_accept_http1(..)` function (#3461)
this commit removes a duplicate function that was errantly defined, due
to some issues when merging previous (interdependent) pr's.

see
- #3455
- #3454
- linkerd/linkerd2#8733

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-13 16:38:42 +00:00
katelyn martin 03f557791c
chore(hyper): upgrade hyper to include hyperium/hyper#3796 (#3457)
* chore(hyper): define hyper as a workspace dependency

this commit alters various crates' manifests, pointing to a common
workspace-level hyper dependency.

note that the lockfile is not altered, this commit does *not* affect the
version of hyper used, or have any other affect on the dependency graph.
this will make future maintenance, upgrading, and patching of our hyper
dependency marginally easier.

see linkerd/linkerd2#8733 for more information on upgrading to hyper
1.0.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(hyper): upgrade hyper to include hyperium/hyper#3796

this commit bumps the version of the workspace's hyper dependency to
include hyperium/hyper#3796, which backports the server connection
builder's `max_pending_accept_reset_streams()` method.

see linkerd/linkerd2#8733 for more information on upgrading to hyper 1.0.

this commit is based upon #3456.

to show the hyper commit in the context of the git log:

```sh
; basename $(pwd)
hyper

; git remote get-url upstream
git@github.com:hyperium/hyper.git

; git log --oneline --decorate 0.14.x -5
a24f0c0a (HEAD -> 0.14.x, upstream/0.14.x) feat(server): backport `max_pending_accept_reset_streams()` to builder (#3796)
96550840 chore(ci): pin hashbrown for MSRV job (#3797)
7829148b (tag: v0.14.31) v0.14.31
97b595e5 perf(http1): improve parsing of sequentially partial messages
739d5e63 chore(ci): pin some deps for MSRV job
```

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(deny.toml): add `hyperium/hyper` to git allowlist

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-13 11:16:15 -05:00
katelyn martin c740b6d872
chore(hyper): define hyper as a workspace dependency (#3456)
this commit alters various crates' manifests, pointing to a common
workspace-level hyper dependency.

note that the lockfile is not altered, this commit does *not* affect the
version of hyper used, or have any other affect on the dependency graph.
this will make future maintenance, upgrading, and patching of our hyper
dependency marginally easier.

see linkerd/linkerd2#8733 for more information on upgrading to hyper
1.0.

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-13 11:15:33 -05:00
katelyn martin f9e65f835d
chore(fuzz): address hyper deprecations in fuzz tests (#3455)
* chore(app/inbound): address hyper deprecations in http/1 tests

this is a follow-up commit related to 24dc5d8a (#3445).

see <https://github.com/linkerd/linkerd2/issues/8733> for more
information on upgrading to hyper 1.0.

---

this addresses hyper deprecations in the http/1 tests for the inbound
proxy.

prior, we made use of `tower::ServiceExt::oneshot`, which consumes a
service and drops it after sending a request and polling the response
future to completion.

<https://docs.rs/tower/0.5.2/src/tower/util/oneshot.rs.html#96-100>

tower is not a 1.0 library yet, so `SendRequest` does not provide an
implementation of `tower::Service` in hyper's 1.0 interface:

- <https://docs.rs/hyper/0.14.31/hyper/client/conn/struct.SendRequest.html#impl-Service%3CRequest%3CB%3E%3E-for-SendRequest%3CB%3E>
- <https://docs.rs/hyper/1.5.1/hyper/client/conn/http1/struct.SendRequest.html#trait-implementations>

consequentially, we must drop the sender ourselves after receiving a
response now.

---

this commit *also* addresses hyper deprecations in the http/1 downgrade
tests for the inbound proxy.

because these tests involve a http/2 client and an http/1 server, we
take the choice of inlining the body of
`http_util::connect_and_accept()` rather than introducing a new, third
`http_util::connect_and_accept_http_downgrade()` function.

we will refactor these helper functions in follow-on commits.

NB: because `ContextError` is internal to the `linkerd-app-test` crate,
we do not wrap the errors. these are allegedly used by the fuzzing tests
(_see f.ex #986 and #989_), but for our purposes with respect to the
inbound proxy we can elide them rather than making `ctx()` a public
method.

---

Signed-off-by: katelyn martin <kate@buoyant.io>

* refactor(app/test): remove unused `http_util::connect_and_accept(..)`

this removes `connect_and_accept(..)`. this will break fuzzing builds,
but it is not used elsewhere.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(fuzz): address hyper deprecation in inbound fuzz tests

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(fuzz): address preëxisting fuzz breakage

this commit addresses other breakage found in the fuzz tests, tied to
other previous work.

after these changes, one can observe that the fuzz tests build and run
once more by running the following:

```sh
cargo +nightly fuzz run --fuzz-dir=linkerd/app/inbound/fuzz/ fuzz_target_1
```

Signed-off-by: katelyn martin <kate@buoyant.io>

* nit(fuzz): remove stray newline from manifest

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-13 11:14:10 -05:00
katelyn martin 42fe4cf666
chore(app/inbound): address hyper deprecations in http/1 tests (#3454)
this is a follow-up commit related to 24dc5d8a (#3445).

see <https://github.com/linkerd/linkerd2/issues/8733> for more
information on upgrading to hyper 1.0.

---

this addresses hyper deprecations in the http/1 tests for the inbound
proxy.

prior, we made use of `tower::ServiceExt::oneshot`, which consumes a
service and drops it after sending a request and polling the response
future to completion.

<https://docs.rs/tower/0.5.2/src/tower/util/oneshot.rs.html#96-100>

tower is not a 1.0 library yet, so `SendRequest` does not provide an
implementation of `tower::Service` in hyper's 1.0 interface:

- <https://docs.rs/hyper/0.14.31/hyper/client/conn/struct.SendRequest.html#impl-Service%3CRequest%3CB%3E%3E-for-SendRequest%3CB%3E>
- <https://docs.rs/hyper/1.5.1/hyper/client/conn/http1/struct.SendRequest.html#trait-implementations>

consequentially, we must drop the sender ourselves after receiving a
response now.

---

this commit *also* addresses hyper deprecations in the http/1 downgrade
tests for the inbound proxy.

because these tests involve a http/2 client and an http/1 server, we
take the choice of inlining the body of
`http_util::connect_and_accept()` rather than introducing a new, third
`http_util::connect_and_accept_http_downgrade()` function.

we will refactor these helper functions in follow-on commits.

NB: because `ContextError` is internal to the `linkerd-app-test` crate,
we do not wrap the errors. these are allegedly used by the fuzzing tests
(_see f.ex #986 and #989_), but for our purposes with respect to the
inbound proxy we can elide them rather than making `ctx()` a public
method.

---

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-13 11:13:48 -05:00
katelyn martin e9e2a31afd
chore(deny.toml): remove stale `idna` directive (#3458)
if one runs `cargo deny check` on the current state of main, or checks
deny logs in ci, one observes this waning:

```sh
$ cargo deny check
warning[unnecessary-skip]: skip 'idna' applied to a crate with only one version
   ┌─ /path/to/linkerd/linkerd2-proxy/deny.toml:63:15
   │
63 │     { name = "idna" },
   │               ━━━━ unnecessary skip configuration

advisories ok, bans ok, licenses ok, sources ok
```

today, our dependency graph only contains one version of `idna`, which
has since release a 1.0 version:

```sh
$ cargo tree -i -p idna
idna v1.0.3
├── hickory-proto v0.24.2
└── url v2.5.4
```

this commit updates the `deny.toml` file, removing this directive to
permit duplicate versions, now that this is no longer the case.

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-13 06:19:21 -08:00
dependabot[bot] 48ce9a9817
build(deps): bump semver from 1.0.23 to 1.0.24 (#3460)
Bumps [semver](https://github.com/dtolnay/semver) from 1.0.23 to 1.0.24.
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.23...1.0.24)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-13 06:18:52 -08:00
dependabot[bot] 0cfbda69b8
build(deps): bump rustls from 0.23.19 to 0.23.20 (#3453)
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.19 to 0.23.20.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.19...v/0.23.20)

---
updated-dependencies:
- dependency-name: rustls
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-12 10:48:38 -08:00
Scott Fleener bb6e9b7f94
chore(deps): Upgrade tokio-rustls to 0.26 (#3419)
chore(deps): Upgrade tokio-rustls to 0.26

This bumps rustls itself from 0.21 to 0.23, which comes with a few breaking API changes. Most of these are limited to types being moved or renamed, or how the certificate verifiers are constructed.

Signed-off-by: Scott Fleener <scott@buoyant.io>
Co-authored-by: Oliver Gould <ver@buoyant.io>
2024-12-11 17:37:03 +00:00
katelyn martin 24dc5d8a1b
chore(app/inbound): address hyper deprecations in http/2 tests (#3445)
this addresses deprecations in inbound proxy tests that should migrate
to hyper's new http/2 client connection builder.

http/1 tests will be upgraded in a follow-on commit.

the `connect_and_accept(..)` helper function is copied, and duplicated
into an http/2 version.

see <https://github.com/linkerd/linkerd2/issues/8733> for more
information on upgrading to hyper 1.0.

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-11 11:37:25 -05:00
katelyn martin 307dbc447a
chore(hyper): address miscellaneous deprecations (#3444)
* chore(proxy/tap): address `Http` deprecation

this is a trivial deprecation fix, for
<https://github.com/linkerd/linkerd2/issues/8733>.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/outbound): address `Http` deprecation

see <https://github.com/linkerd/linkerd2/issues/8733>.

this updates some test code to use the backported server connection
interfaces.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/integration): address `conn::Builder` deprecation

this commit addresses uses of deprecated hyper interfaces in the
`linkerd-app-integration` crate.

see <https://github.com/linkerd/linkerd2/issues/8733>.

Signed-off-by: katelyn martin <kate@buoyant.io>

* chore(app/inbound): remove stale `deprecated` allowance

this was fixed in a previous commit.

Signed-off-by: katelyn martin <kate@buoyant.io>

---------

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-11 11:37:02 -05:00
katelyn martin f31cf1f4f7
chore(gitignore): ignore `.cargo` directory (#3451)
this commit supercedes #3443.

we use the kubert crate to export a collection of metrics measuring the
behavior of our asynchronous tokio runtime.

in order for this crate to compile, one must set a compile-time flag.
this can be done either by setting the RUSTFLAGS environment variable,
or via a toml file in .cargo/config.toml.

helpful links:

- <https://github.com/olix0r/kubert?tab=readme-ov-file#kubert-prometheus-tokio>
- <https://docs.rs/tokio-metrics/latest/tokio_metrics/>
- <https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags>

this commit adds `.cargo` to the repository's gitignore, so that people
may freely modify cargo configuration as needed when building the
project from source.

Signed-off-by: katelyn martin <kate@buoyant.io>
2024-12-11 11:35:07 -05:00
dependabot[bot] d2cc5c975d
build(deps): bump EmbarkStudios/cargo-deny-action from 1.6.3 to 2.0.4 (#3412)
Bumps [EmbarkStudios/cargo-deny-action](https://github.com/embarkstudios/cargo-deny-action) from 1.6.3 to 2.0.4.
- [Release notes](https://github.com/embarkstudios/cargo-deny-action/releases)
- [Commits](3f4a782664...e2f4ede4a4)

---
updated-dependencies:
- dependency-name: EmbarkStudios/cargo-deny-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-11 15:37:08 +00:00
dependabot[bot] b1a43854d8
build(deps): bump hickory-proto from 0.24.1 to 0.24.2 (#3447)
Bumps [hickory-proto](https://github.com/hickory-dns/hickory-dns) from 0.24.1 to 0.24.2.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.2/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.1...v0.24.2)

---
updated-dependencies:
- dependency-name: hickory-proto
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-11 07:07:15 -08:00
dependabot[bot] 37ddadafb5
build(deps): bump hickory-resolver from 0.24.1 to 0.24.2 (#3448)
Bumps [hickory-resolver](https://github.com/hickory-dns/hickory-dns) from 0.24.1 to 0.24.2.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.2/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.1...v0.24.2)

---
updated-dependencies:
- dependency-name: hickory-resolver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-11 07:06:43 -08:00
dependabot[bot] 8cdbe70491
build(deps): bump softprops/action-gh-release from 2.1.0 to 2.2.0 (#3450)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](01570a1f39...7b4da11513)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-11 07:06:20 -08:00
dependabot[bot] 356eb4b669
build(deps): bump serde from 1.0.215 to 1.0.216 (#3449)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.215 to 1.0.216.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.216)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-11 07:05:59 -08:00
dependabot[bot] e0e1daddb0
build(deps): bump governor from 0.7.0 to 0.8.0 (#3446)
Bumps [governor](https://github.com/boinkor-net/governor) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/boinkor-net/governor/releases)
- [Changelog](https://github.com/boinkor-net/governor/blob/master/release.toml)
- [Commits](https://github.com/boinkor-net/governor/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: governor
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-11 07:05:36 -08:00
400 changed files with 11448 additions and 9019 deletions

View File

@ -3,7 +3,7 @@
"build": {
"dockerfile": "Dockerfile",
"args": {
"DEV_VERSION": "v44",
"DEV_VERSION": "v47",
"http_proxy": "${localEnv:http_proxy}",
"https_proxy": "${localEnv:https_proxy}"
}
@ -23,7 +23,15 @@
"zxh404.vscode-proto3"
],
"settings": {
"files.insertFinalNewline": true
"files.insertFinalNewline": true,
"[git-commit]": {
"editor.rulers": [
72,
80
],
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80
}
}
}
},
@ -42,7 +50,7 @@
"overrideCommand": false,
"remoteUser": "code",
"containerEnv": {
"CXX": "clang++-14",
"CXX": "clang++-19",
"RUSTFLAGS": "--cfg tokio_unstable"
},
"mounts": [

156
.github/copilot-instructions.md vendored Normal file
View File

@ -0,0 +1,156 @@
# Linkerd2 Proxy Copilot Instructions
## Code Generation
- Code MUST pass `cargo fmt`.
- Code MUST pass `cargo clippy --all-targets --all-features -- -D warnings`.
- Markdown MUST pass `markdownlint-cli2`.
- Prefer `?` for error propagation.
- Avoid `unwrap()` and `expect()` outside tests.
- Use `tracing` crate macros (`tracing::info!`, etc.) for structured logging.
### Comments
Comments should explain **why**, not **what**. Focus on high-level rationale and
design intent at the function or block level, rather than line-by-line
descriptions.
- Use comments to capture:
- System-facing or interface-level concerns
- Key invariants, preconditions, and postconditions
- Design decisions and trade-offs
- Cross-references to architecture or design documentation
- Avoid:
- Line-by-line commentary explaining obvious code
- Restating what the code already clearly expresses
- For public APIs:
- Use `///` doc comments to describe the contract, behavior, parameters, and
usage examples
- For internal rationale:
- Use `//` comments sparingly to note non-obvious reasoning or edge-case
handling
- Be neutral and factual.
### Rust File Organization
For Rust source files, enforce this layout:
1. **Nonpublic imports**
- Declare all `use` statements for private/internal crates first.
- Group imports to avoid duplicates and do **not** add blank lines between
`use` statements.
2. **Module declarations**
- List all `mod` declarations.
3. **Reexports**
- Follow with `pub use` statements.
4. **Type definitions**
- Define `struct`, `enum`, `type`, and `trait` declarations.
- Sort by visibility: `pub` first, then `pub(crate)`, then private.
- Public types should be documented with `///` comments.
5. **Impl blocks**
- Implement methods in the same order as types above.
- Precede each types `impl` block with a header comment: `// === <TypeName> ===`
6. **Tests**
- End with a `tests` module guarded by `#[cfg(test)]`.
- If the infile test module exceeds 100lines, move it to
`tests/<filename>.rs` as a child integrationtest module.
## Test Generation
- Async tests MUST use `tokio::test`.
- Synchronous tests use `#[test]`.
- Include at least one failingedgecase test per public function.
- Use `tracing::info!` for logging in tests, usually in place of comments.
## Code Review
### Rust
- Point out any `unsafe` blocks and justify their safety.
- Flag functions >50 LOC for refactor suggestions.
- Highlight missing docs on public items.
### Markdown
- Use `markdownlint-cli2` to check for linting errors.
- Lines SHOULD be wrapped at 80 characters.
- Fenced code blocks MUST include a language identifier.
### Copilot Instructions
- Start each instruction with an imperative, presenttense verb.
- Keep each instruction under 120 characters.
- Provide one directive per instruction; avoid combining multiple ideas.
- Use "MUST" and "SHOULD" sparingly to emphasize critical rules.
- Avoid semicolons and complex punctuation within bullets.
- Do not reference external links, documents, or specific coding standards.
## Commit Messages
Commits follow the Conventional Commits specification:
### Subject
Subjects are in the form: `<type>[optional scope]: <description>`
- **Type**: feat, fix, docs, refactor, test, chore, ci, build, perf, revert
(others by agreement)
- **Scope**: optional, lowercase; may include `/` to denote submodules (e.g.
`http/detect`)
- **Description**: imperative mood, present tense, no trailing period
- MUST be less than 72 characters
- Omit needless words!
### Body
Non-trivial commits SHOULD include a body summarizing the change.
- Explain *why* the change was needed.
- Describe *what* was done at a high level.
- Use present-tense narration.
- Use complete sentences, paragraphs, and punctuation.
- Preceded by a blank line.
- Wrapped at 80 characters.
- Omit needless words!
### Breaking changes
If the change introduces a backwards-incompatible change, it MUST be marked as
such.
- Indicated by `!` after the type/scope (e.g. `feat(inbound)!: …`)
- Optionally including a `BREAKING CHANGE:` section in the footer explaining the
change in behavior.
### Examples
```text
feat(auth): add JWT refresh endpoint
There is currently no way to refresh a JWT token.
This exposes a new `/refresh` route that returns a refreshed token.
```
```text
feat(api)!: remove deprecated v1 routes
The `/v1/*` endpoints have been deprecated for a long time and are no
longer called by clients.
This change removes the `/v1/*` endpoints and all associated code,
including integration tests and documentation.
BREAKING CHANGE: The previously-deprecated `/v1/*` endpoints were removed.
```
## Pull Requests
- The subject line MUST be in the conventional commit format.
- Autogenerate a PR body summarizing the problem, solution, and verification steps.
- List breaking changes under a separate **Breaking Changes** heading.

View File

@ -11,12 +11,6 @@ updates:
allow:
- dependency-type: "all"
ignore:
# These dependencies will be updated via higher-level aggregator dependencies like `clap`,
# `futures`, `prost`, `tracing`, and `trust-dns-resolver`:
- dependency-name: "futures-*"
- dependency-name: "prost-derive"
- dependency-name: "tracing-*"
- dependency-name: "trust-dns-proto"
# These dependencies are for platforms that we don't support:
- dependency-name: "hermit-abi"
- dependency-name: "redox_*"
@ -25,9 +19,37 @@ updates:
- dependency-name: "web-sys"
- dependency-name: "windows*"
groups:
boring:
patterns:
- "tokio-boring"
- "boring*"
futures:
patterns:
- "futures*"
grpc:
patterns:
- "prost*"
- "tonic*"
hickory:
patterns:
- "hickory*"
icu4x:
patterns:
- "icu_*"
opentelemetry:
patterns:
- "opentelemetry*"
rustls:
patterns:
- "tokio-rustls"
- "rustls*"
- "ring"
symbolic:
patterns:
- "symbolic-*"
tracing:
patterns:
- "tracing*"
- package-ecosystem: cargo
directory: /linkerd/addr/fuzz

View File

@ -22,13 +22,13 @@ permissions:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/linkerd/dev:v44-rust
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
container: ghcr.io/linkerd/dev:v47-rust
timeout-minutes: 20
continue-on-error: true
steps:
- run: rustup toolchain install --profile=minimal beta
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- run: git config --global --add safe.directory "$PWD" # actions/runner#2033
- run: just toolchain=beta fetch
- run: just toolchain=beta build

View File

@ -21,11 +21,11 @@ env:
jobs:
meta:
timeout-minutes: 5
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- id: changed
uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with:
files: |
.codecov.yml
@ -40,19 +40,19 @@ jobs:
codecov:
needs: meta
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || needs.meta.outputs.any_changed == 'true'
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
timeout-minutes: 30
container:
image: docker://ghcr.io/linkerd/dev:v44-rust
image: docker://ghcr.io/linkerd/dev:v47-rust
options: --security-opt seccomp=unconfined # 🤷
env:
CXX: "/usr/bin/clang++-14"
CXX: "/usr/bin/clang++-19"
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0
- run: cargo tarpaulin --locked --workspace --exclude=linkerd2-proxy --exclude=linkerd-transport-header --exclude=opencensus-proto --exclude=spire-proto --no-run
- run: cargo tarpaulin --locked --workspace --exclude=linkerd2-proxy --exclude=linkerd-transport-header --exclude=opencensus-proto --exclude=spire-proto --skip-clean --ignore-tests --no-fail-fast --out=Xml
# Some tests are especially flakey in coverage tests. That's fine. We
# only really care to measure how much of our codebase is covered.
continue-on-error: true
- uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24

View File

@ -26,13 +26,13 @@ permissions:
jobs:
list-changed:
timeout-minutes: 3
runs-on: ubuntu-latest
container: docker://rust:1.83.0
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
container: docker://rust:1.88.0
steps:
- run: apt update && apt install -y jo
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- run: git config --global --add safe.directory "$PWD" # actions/runner#2033
- uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366
- uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
id: changed-files
- name: list changed crates
id: list-changed
@ -47,15 +47,15 @@ jobs:
build:
needs: [list-changed]
timeout-minutes: 40
runs-on: ubuntu-latest
container: docker://rust:1.83.0
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
container: docker://rust:1.88.0
strategy:
matrix:
dir: ${{ fromJson(needs.list-changed.outputs.dirs) }}
steps:
- run: rustup toolchain add nightly
- run: cargo install cargo-fuzz
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- run: git config --global --add safe.directory "$PWD" # actions/runner#2033
- working-directory: ${{matrix.dir}}
run: cargo +nightly fetch

View File

@ -12,9 +12,9 @@ on:
jobs:
markdownlint:
timeout-minutes: 5
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: DavidAnson/markdownlint-cli2-action@eb5ca3ab411449c66620fe7f1b3c9e10547144b0
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- uses: DavidAnson/markdownlint-cli2-action@992badcdf24e3b8eb7e87ff9287fe931bcb00c6e
with:
globs: "**/*.md"

View File

@ -22,13 +22,13 @@ permissions:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/linkerd/dev:v44-rust
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
container: ghcr.io/linkerd/dev:v47-rust
timeout-minutes: 20
continue-on-error: true
steps:
- run: rustup toolchain install --profile=minimal nightly
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- run: git config --global --add safe.directory "$PWD" # actions/runner#2033
- run: just toolchain=nightly fetch
- run: just toolchain=nightly profile=release build

View File

@ -14,24 +14,24 @@ concurrency:
jobs:
meta:
timeout-minutes: 5
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- id: build
uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with:
files: |
.github/workflows/pr.yml
justfile
Dockerfile
- id: actions
uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with:
files: |
.github/workflows/**
.devcontainer/*
- id: cargo
uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with:
files_ignore: "Cargo.toml"
files: |
@ -40,7 +40,7 @@ jobs:
if: steps.cargo.outputs.any_changed == 'true'
run: ./.github/list-crates.sh ${{ steps.cargo.outputs.all_changed_files }}
- id: rust
uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with:
files: |
**/*.rs
@ -57,7 +57,7 @@ jobs:
info:
timeout-minutes: 3
needs: meta
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- name: Info
run: |
@ -74,30 +74,27 @@ jobs:
actions:
needs: meta
if: needs.meta.outputs.actions_changed == 'true'
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- uses: linkerd/dev/actions/setup-tools@v44
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: linkerd/dev/actions/setup-tools@v47
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- run: just action-lint
- run: just action-dev-check
rust:
needs: meta
if: needs.meta.outputs.cargo_changed == 'true' || needs.meta.outputs.rust_changed == 'true'
runs-on: ubuntu-latest
container: ghcr.io/linkerd/dev:v44-rust
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
container: ghcr.io/linkerd/dev:v47-rust
permissions:
contents: read
timeout-minutes: 20
steps:
- run: git config --global --add safe.directory "$PWD" # actions/runner#2033
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0
- run: just fetch
- name: Run cargo deny check bans licenses sources
uses: EmbarkStudios/cargo-deny-action@3f4a782664881cf5725d0ffd23969fcce89fd868
with:
command: check bans licenses sources
- run: cargo deny --all-features check bans licenses sources
- run: just check-fmt
- run: just clippy
- run: just doc
@ -110,15 +107,15 @@ jobs:
needs: meta
if: needs.meta.outputs.cargo_changed == 'true'
timeout-minutes: 20
runs-on: ubuntu-latest
container: ghcr.io/linkerd/dev:v44-rust
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
container: ghcr.io/linkerd/dev:v47-rust
strategy:
matrix:
crate: ${{ fromJson(needs.meta.outputs.cargo_crates) }}
steps:
- run: git config --global --add safe.directory "$PWD" # actions/runner#2033
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0
- run: just fetch
- run: just check-crate ${{ matrix.crate }}
@ -126,11 +123,11 @@ jobs:
needs: meta
if: needs.meta.outputs.cargo_changed == 'true' || needs.meta.outputs.rust_changed == 'true'
timeout-minutes: 20
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
env:
WAIT_TIMEOUT: 2m
steps:
- uses: linkerd/dev/actions/setup-tools@v44
- uses: linkerd/dev/actions/setup-tools@v47
- name: scurl https://run.linkerd.io/install-edge | sh
run: |
scurl https://run.linkerd.io/install-edge | sh
@ -139,9 +136,9 @@ jobs:
tag=$(linkerd version --client --short)
echo "linkerd $tag"
echo "LINKERD_TAG=$tag" >> "$GITHUB_ENV"
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- run: just docker
- run: just-k3d create
- run: just k3d-create
- run: just k3d-load-linkerd
- run: just linkerd-install
- run: just linkerd-check-control-plane-proxy
@ -152,7 +149,7 @@ jobs:
timeout-minutes: 3
needs: [meta, actions, rust, rust-crates, linkerd-install]
if: always()
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
permissions:
contents: write
@ -171,7 +168,7 @@ jobs:
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
run: exit 1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
if: needs.meta.outputs.is_dependabot == 'true' && needs.meta.outputs.any_changed == 'true'
- name: "Merge dependabot changes"
if: needs.meta.outputs.is_dependabot == 'true' && needs.meta.outputs.any_changed == 'true'

View File

@ -13,7 +13,7 @@ concurrency:
jobs:
last-release:
if: github.repository == 'linkerd/linkerd2-proxy' # Don't run this in forks.
runs-on: ubuntu-22.04
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
timeout-minutes: 5
env:
GH_REPO: ${{ github.repository }}
@ -41,10 +41,10 @@ jobs:
last-commit:
needs: last-release
runs-on: ubuntu-22.04
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
timeout-minutes: 5
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- name: Check if the most recent commit is after the last release
id: recency
env:
@ -62,7 +62,7 @@ jobs:
trigger-release:
needs: [last-release, last-commit]
if: needs.last-release.outputs.recent == 'false' && needs.last-commit.outputs.after-release == 'true'
runs-on: ubuntu-22.04
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
timeout-minutes: 5
permissions:
actions: write

View File

@ -46,6 +46,7 @@ on:
default: true
env:
CARGO: "cargo auditable"
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTFLAGS: "-D warnings -A deprecated --cfg tokio_unstable"
@ -58,9 +59,25 @@ concurrency:
jobs:
meta:
timeout-minutes: 5
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- id: meta
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
if: github.event_name == 'pull_request'
- id: workflow
if: github.event_name == 'pull_request'
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with:
files: |
.github/workflows/release.yml
- id: build
if: github.event_name == 'pull_request'
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with:
files: |
justfile
Cargo.toml
- id: version
env:
VERSION: ${{ inputs.version }}
shell: bash
@ -68,44 +85,45 @@ jobs:
set -euo pipefail
shopt -s extglob
if [[ "$GITHUB_EVENT_NAME" == pull_request ]]; then
echo version="0.0.0-test.${GITHUB_SHA:0:7}"
echo archs='["amd64"]'
echo version="0.0.0-test.${GITHUB_SHA:0:7}" >> "$GITHUB_OUTPUT"
exit 0
fi >> "$GITHUB_OUTPUT"
fi
if ! [[ "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+)?(\+[0-9A-Za-z-]+)?$ ]]; then
echo "Invalid version: $VERSION" >&2
exit 1
fi
( echo version="${VERSION#v}"
echo archs='["amd64", "arm64", "arm"]'
echo version="${VERSION#v}" >> "$GITHUB_OUTPUT"
- id: platform
shell: bash
env:
WORKFLOW_CHANGED: ${{ steps.workflow.outputs.any_changed }}
run: |
if [[ "$GITHUB_EVENT_NAME" == pull_request && "$WORKFLOW_CHANGED" != 'true' ]]; then
( echo archs='["amd64"]'
echo oses='["linux"]' ) >> "$GITHUB_OUTPUT"
exit 0
fi
( echo archs='["amd64", "arm64"]'
echo oses='["linux", "windows"]'
) >> "$GITHUB_OUTPUT"
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
if: github.event_name == 'pull_request'
- id: changed
if: github.event_name == 'pull_request'
uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366
with:
files: |
.github/workflows/release.yml
justfile
Cargo.toml
outputs:
archs: ${{ steps.meta.outputs.archs }}
version: ${{ steps.meta.outputs.version }}
package: ${{ github.event_name == 'workflow_dispatch' || steps.changed.outputs.any_changed == 'true' }}
archs: ${{ steps.platform.outputs.archs }}
oses: ${{ steps.platform.outputs.oses }}
version: ${{ steps.version.outputs.version }}
package: ${{ github.event_name == 'workflow_dispatch' || steps.build.outputs.any_changed == 'true' || steps.workflow.outputs.any_changed == 'true' }}
profile: ${{ inputs.profile || 'release' }}
publish: ${{ inputs.publish }}
ref: ${{ inputs.ref || github.sha }}
tag: "${{ inputs.tag-prefix || 'release/' }}v${{ steps.meta.outputs.version }}"
tag: "${{ inputs.tag-prefix || 'release/' }}v${{ steps.version.outputs.version }}"
prerelease: ${{ inputs.prerelease }}
draft: ${{ inputs.draft }}
latest: ${{ inputs.latest }}
info:
needs: meta
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
timeout-minutes: 3
steps:
- name: Inputs
@ -126,38 +144,50 @@ jobs:
strategy:
matrix:
arch: ${{ fromJson(needs.meta.outputs.archs) }}
os: ${{ fromJson(needs.meta.outputs.oses) }}
libc: [gnu] # musl
exclude:
- os: windows
arch: arm64
# If we're not actually building on a release tag, don't short-circuit on
# errors. This helps us know whether a failure is platform-specific.
continue-on-error: ${{ needs.meta.outputs.publish != 'true' }}
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
timeout-minutes: 40
container: docker://ghcr.io/linkerd/dev:v44-rust-musl
container: docker://ghcr.io/linkerd/dev:v47-rust-musl
env:
LINKERD2_PROXY_VENDOR: ${{ github.repository_owner }}
LINKERD2_PROXY_VERSION: ${{ needs.meta.outputs.version }}
steps:
# TODO: add to dev image
- name: Install MiniGW
if: matrix.os == 'windows'
run: apt-get update && apt-get install -y mingw-w64
- name: Install cross compilation toolchain
if: matrix.arch == 'arm64'
run: apt-get update && apt-get install -y binutils-aarch64-linux-gnu
- name: Configure git
run: git config --global --add safe.directory "$PWD" # actions/runner#2033
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
with:
ref: ${{ needs.meta.outputs.ref }}
- uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0
with:
key: ${{ matrix.arch }}
key: ${{ matrix.os }}-${{ matrix.arch }}
- run: just fetch
- run: just arch=${{ matrix.arch }} libc=${{ matrix.libc }} rustup
- run: just arch=${{ matrix.arch }} libc=${{ matrix.libc }} profile=${{ needs.meta.outputs.profile }} build
- run: just arch=${{ matrix.arch }} libc=${{ matrix.libc }} profile=${{ needs.meta.outputs.profile }} package
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
- run: just arch=${{ matrix.arch }} libc=${{ matrix.libc }} os=${{ matrix.os }} rustup
- run: just arch=${{ matrix.arch }} libc=${{ matrix.libc }} os=${{ matrix.os }} profile=${{ needs.meta.outputs.profile }} build
- run: just arch=${{ matrix.arch }} libc=${{ matrix.libc }} os=${{ matrix.os }} profile=${{ needs.meta.outputs.profile }} package
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: ${{ matrix.arch }}-artifacts
name: ${{ matrix.arch }}-${{ matrix.os }}-artifacts
path: target/package/*
publish:
needs: [meta, package]
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
timeout-minutes: 5
permissions:
actions: write
@ -174,13 +204,13 @@ jobs:
git config --global user.name "$GITHUB_USERNAME"
git config --global user.email "$GITHUB_USERNAME"@users.noreply.github.com
# Tag the release.
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
with:
token: ${{ secrets.LINKERD2_PROXY_GITHUB_TOKEN || github.token }}
ref: ${{ needs.meta.outputs.ref }}
- run: git tag -a -m "$VERSION" "$TAG"
# Fetch the artifacts.
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
path: artifacts
- run: du -h artifacts/**/*
@ -188,7 +218,7 @@ jobs:
- if: needs.meta.outputs.publish == 'true'
run: git push origin "$TAG"
- if: needs.meta.outputs.publish == 'true'
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
name: ${{ env.VERSION }}
tag_name: ${{ env.TAG }}
@ -212,7 +242,7 @@ jobs:
needs: publish
if: always()
timeout-minutes: 3
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- name: Results
run: |

View File

@ -13,8 +13,8 @@ on:
jobs:
sh-lint:
timeout-minutes: 5
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- uses: linkerd/dev/actions/setup-tools@v44
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: linkerd/dev/actions/setup-tools@v47
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- run: just sh-lint

View File

@ -13,10 +13,10 @@ permissions:
jobs:
devcontainer:
runs-on: ubuntu-latest
container: ghcr.io/linkerd/dev:v44-rust
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
container: ghcr.io/linkerd/dev:v47-rust
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- run: git config --global --add safe.directory "$PWD" # actions/runner#2033
- run: |
VERSION_REGEX='channel = "([0-9]+\.[0-9]+\.[0-9]+)"'
@ -35,10 +35,10 @@ jobs:
workflows:
runs-on: ubuntu-latest
runs-on: ${{ vars.LINKERD2_PROXY_RUNNER || 'ubuntu-24.04' }}
steps:
- uses: linkerd/dev/actions/setup-tools@v44
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: linkerd/dev/actions/setup-tools@v47
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- shell: bash
run: |
VERSION_REGEX='channel = "([0-9]+\.[0-9]+\.[0-9]+)"'

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
.cargo
**/.cargo
target
**/target
**/corpus

2060
Cargo.lock

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,6 @@ members = [
"linkerd/app",
"linkerd/conditional",
"linkerd/distribute",
"linkerd/detect",
"linkerd/dns/name",
"linkerd/dns",
"linkerd/duplex",
@ -27,7 +26,7 @@ members = [
"linkerd/http/access-log",
"linkerd/http/box",
"linkerd/http/classify",
"linkerd/http/executor",
"linkerd/http/detect",
"linkerd/http/h2",
"linkerd/http/insert",
"linkerd/http/metrics",
@ -38,15 +37,14 @@ members = [
"linkerd/http/route",
"linkerd/http/stream-timeouts",
"linkerd/http/upgrade",
"linkerd/http/version",
"linkerd/http/variant",
"linkerd/identity",
"linkerd/idle-cache",
"linkerd/io",
"linkerd/meshtls",
"linkerd/meshtls/boring",
"linkerd/meshtls/rustls",
"linkerd/meshtls/verifier",
"linkerd/metrics",
"linkerd/mock/http-body",
"linkerd/opaq-route",
"linkerd/opencensus",
"linkerd/opentelemetry",
@ -71,12 +69,12 @@ members = [
"linkerd/reconnect",
"linkerd/retry",
"linkerd/router",
"linkerd/rustls",
"linkerd/service-profiles",
"linkerd/signal",
"linkerd/stack",
"linkerd/stack/metrics",
"linkerd/stack/tracing",
"linkerd/system",
"linkerd/tonic-stream",
"linkerd/tonic-watch",
"linkerd/tls",
@ -85,6 +83,7 @@ members = [
"linkerd/tracing",
"linkerd/transport-header",
"linkerd/transport-metrics",
"linkerd/workers",
"linkerd2-proxy",
"opencensus-proto",
"opentelemetry-proto",
@ -96,6 +95,43 @@ members = [
debug = 1
lto = true
[workspace.package]
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
[workspace.dependencies]
linkerd2-proxy-api = "0.15.0"
# linkerd2-proxy-api = { git = "https://github.com/linkerd/linkerd2-proxy-api.git", branch = "main" }
bytes = { version = "1" }
drain = { version = "0.2", default-features = false }
h2 = { version = "0.4" }
http = { version = "1" }
http-body = { version = "1" }
hyper = { version = "1", default-features = false }
prometheus-client = { version = "0.23" }
prost = { version = "0.13" }
prost-build = { version = "0.13", default-features = false }
prost-types = { version = "0.13" }
tokio-rustls = { version = "0.26", default-features = false, features = [
"logging",
] }
tonic = { version = "0.13", default-features = false }
tonic-build = { version = "0.13", default-features = false }
tower = { version = "0.5", default-features = false }
tower-service = { version = "0.3" }
tower-test = { version = "0.4" }
tracing = { version = "0.1" }
[workspace.dependencies.http-body-util]
version = "0.1.3"
default-features = false
features = ["channel"]
[workspace.dependencies.hyper-util]
version = "0.1"
default-features = false
features = ["tokio", "tracing"]
[workspace.dependencies.linkerd2-proxy-api]
version = "0.17.0"

View File

@ -3,7 +3,7 @@
# This is intended **DEVELOPMENT ONLY**, i.e. so that proxy developers can
# easily test the proxy in the context of the larger `linkerd2` project.
ARG RUST_IMAGE=ghcr.io/linkerd/dev:v44-rust
ARG RUST_IMAGE=ghcr.io/linkerd/dev:v47-rust
# Use an arbitrary ~recent edge release image to get the proxy
# identity-initializing and linkerd-await wrappers.
@ -14,11 +14,16 @@ FROM $LINKERD2_IMAGE as linkerd2
FROM --platform=$BUILDPLATFORM $RUST_IMAGE as fetch
ARG PROXY_FEATURES=""
ARG TARGETARCH="amd64"
RUN apt-get update && \
apt-get install -y time && \
if [[ "$PROXY_FEATURES" =~ .*meshtls-boring.* ]] ; then \
apt-get install -y golang ; \
fi && \
case "$TARGETARCH" in \
amd64) true ;; \
arm64) apt-get install --no-install-recommends -y binutils-aarch64-linux-gnu ;; \
esac && \
rm -rf /var/lib/apt/lists/*
ENV CARGO_NET_RETRY=10
@ -33,7 +38,6 @@ RUN --mount=type=cache,id=cargo,target=/usr/local/cargo/registry \
FROM fetch as build
ENV CARGO_INCREMENTAL=0
ENV RUSTFLAGS="-D warnings -A deprecated --cfg tokio_unstable"
ARG TARGETARCH="amd64"
ARG PROFILE="release"
ARG LINKERD2_PROXY_VERSION=""
ARG LINKERD2_PROXY_VENDOR=""

View File

@ -86,8 +86,9 @@ minutes to review our [code of conduct][coc].
We test our code by way of fuzzing and this is described in [FUZZING.md](/docs/FUZZING.md).
A third party security audit focused on fuzzing Linkerd2-proxy was performed by
Ada Logics in 2021. The full report is available
[here](/docs/reports/linkerd2-proxy-fuzzing-report.pdf).
Ada Logics in 2021. The
[full report](/docs/reports/linkerd2-proxy-fuzzing-report.pdf) can be found in
the `docs/reports/` directory.
## License

View File

@ -2,7 +2,6 @@
targets = [
{ triple = "x86_64-unknown-linux-gnu" },
{ triple = "aarch64-unknown-linux-gnu" },
{ triple = "armv7-unknown-linux-gnu" },
]
[advisories]
@ -18,27 +17,20 @@ allow = [
"ISC",
"MIT",
"Unicode-3.0",
"Zlib",
]
# Ignore local workspace license values for unpublished crates.
private = { ignore = true }
confidence-threshold = 0.8
exceptions = [
{ allow = [
"Zlib",
], name = "adler32", version = "*" },
"ISC",
"OpenSSL",
], name = "aws-lc-sys", version = "*" },
{ allow = [
"ISC",
"MIT",
"OpenSSL",
], name = "ring", version = "*" },
]
[[licenses.clarify]]
name = "ring"
version = "*"
expression = "MIT AND ISC AND OpenSSL"
license-files = [
{ path = "LICENSE", hash = 0xbd0eed23 },
], name = "aws-lc-fips-sys", version = "*" },
]
[bans]
@ -50,27 +42,35 @@ deny = [
{ name = "rustls", wrappers = ["tokio-rustls"] },
# rustls-webpki should be used instead.
{ name = "webpki" },
# aws-lc-rs should be used instead.
{ name = "ring" }
]
skip = [
# `linkerd-trace-context`, `rustls-pemfile` and `tonic` depend on `base64`
# v0.13.1 while `rcgen` depends on v0.21.5
{ name = "base64" },
{ name = "bitflags", version = "1" },
# https://github.com/hawkw/matchers/pull/4
{ name = "regex-automata", version = "0.1" },
{ name = "regex-syntax", version = "0.6" },
# `trust-dns-proto`, depends on `idna` v0.4.0 while `url` depends on v0.5.0
{ name = "idna" },
# Some dependencies still use indexmap v1.
{ name = "indexmap", version = "1" },
{ name = "hashbrown", version = "0.12" },
# tonic/axum depend on a newer `tower`, which we are still catching up to.
# see #3744.
{ name = "tower", version = "0.5" },
]
skip-tree = [
# thiserror v2 is still propagating through the ecosystem
{ name = "thiserror", version = "1" },
# rand v0.9 is still propagating through the ecosystem
{ name = "rand", version = "0.8" },
# rust v1.0 is still propagating through the ecosystem
{ name = "rustix", version = "0.38" },
# `pprof` uses a number of old dependencies. for now, we skip its subtree.
{ name = "pprof" },
# aws-lc-rs uses a slightly outdated version of bindgen
{ name = "bindgen", version = "0.69.5" },
# socket v0.6 is still propagating through the ecosystem
{ name = "socket2", version = "0.5" },
]
[sources]
unknown-registry = "deny"
unknown-git = "deny"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
allow-registry = [
"https://github.com/rust-lang/crates.io-index",
]

View File

@ -12,9 +12,12 @@ engine.
We place the fuzz tests into folders within the individual crates that the fuzz
tests target. For example, we have a fuzz test that that target the crate
`/linkerd/addr` and the code in `/linkerd/addr/src` and thus the fuzz test that
targets this crate is put in `/linkerd/addr/fuzz`. The folder set up we use for
each of the fuzz tests is automatically generated by `cargo fuzz init`
(described [here](https://github.com/rust-fuzz/cargo-fuzz#cargo-fuzz-init)).
targets this crate is put in `/linkerd/addr/fuzz`.
The folder structure for each of the fuzz tests is automatically generated by
`cargo fuzz init`. See cargo fuzz's
[`README.md`](https://github.com/rust-fuzz/cargo-fuzz#cargo-fuzz-init) for more
information.
### Fuzz targets
@ -96,6 +99,5 @@ unit-test-like fuzzers, but are essentially just more substantial in nature. The
idea behind these fuzzers is to test end-to-end concepts more so than individual
components of the proxy.
The inbound fuzzer
[here](/linkerd/app/inbound/fuzz/fuzz_targets/fuzz_target_1.rs) is an example of
this.
The [inbound fuzzer](/linkerd/app/inbound/fuzz/fuzz_targets/fuzz_target_1.rs)
is an example of this.

View File

@ -1,17 +1,18 @@
[package]
name = "hyper-balance"
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
[dependencies]
futures = { version = "0.3", default-features = false }
http = "0.2"
hyper = { version = "0.14", features = ["deprecated"] }
http = { workspace = true }
http-body = { workspace = true }
hyper = { workspace = true }
pin-project = "1"
tower = { version = "0.4", default-features = false, features = ["load"] }
tower = { workspace = true, default-features = false, features = ["load"] }
tokio = { version = "1", features = ["macros"] }
[dev-dependencies]

View File

@ -1,7 +1,7 @@
#![deny(rust_2018_idioms, clippy::disallowed_methods, clippy::disallowed_types)]
#![forbid(unsafe_code)]
use hyper::body::HttpBody;
use http_body::Body;
use pin_project::pin_project;
use std::pin::Pin;
use std::task::{Context, Poll};
@ -38,7 +38,7 @@ pub struct PendingUntilEosBody<T, B> {
impl<T, B> TrackCompletion<T, http::Response<B>> for PendingUntilFirstData
where
B: HttpBody,
B: Body,
{
type Output = http::Response<PendingUntilFirstDataBody<T, B>>;
@ -59,7 +59,7 @@ where
impl<T, B> TrackCompletion<T, http::Response<B>> for PendingUntilEos
where
B: HttpBody,
B: Body,
{
type Output = http::Response<PendingUntilEosBody<T, B>>;
@ -80,7 +80,7 @@ where
impl<T, B> Default for PendingUntilFirstDataBody<T, B>
where
B: HttpBody + Default,
B: Body + Default,
{
fn default() -> Self {
Self {
@ -90,9 +90,9 @@ where
}
}
impl<T, B> HttpBody for PendingUntilFirstDataBody<T, B>
impl<T, B> Body for PendingUntilFirstDataBody<T, B>
where
B: HttpBody,
B: Body,
T: Send + 'static,
{
type Data = B::Data;
@ -102,32 +102,20 @@ where
self.body.is_end_stream()
}
fn poll_data(
fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
let this = self.project();
let ret = futures::ready!(this.body.poll_data(cx));
let ret = futures::ready!(this.body.poll_frame(cx));
// Once a data frame is received, the handle is dropped. On subsequent calls, this
// Once a frame is received, the handle is dropped. On subsequent calls, this
// is a noop.
drop(this.handle.take());
Poll::Ready(ret)
}
fn poll_trailers(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
let this = self.project();
// If this is being called, the handle definitely should have been dropped
// already.
drop(this.handle.take());
this.body.poll_trailers(cx)
}
#[inline]
fn size_hint(&self) -> hyper::body::SizeHint {
self.body.size_hint()
@ -138,7 +126,7 @@ where
impl<T, B> Default for PendingUntilEosBody<T, B>
where
B: HttpBody + Default,
B: Body + Default,
{
fn default() -> Self {
Self {
@ -148,7 +136,7 @@ where
}
}
impl<T: Send + 'static, B: HttpBody> HttpBody for PendingUntilEosBody<T, B> {
impl<T: Send + 'static, B: Body> Body for PendingUntilEosBody<T, B> {
type Data = B::Data;
type Error = B::Error;
@ -157,35 +145,21 @@ impl<T: Send + 'static, B: HttpBody> HttpBody for PendingUntilEosBody<T, B> {
self.body.is_end_stream()
}
fn poll_data(
fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
let mut this = self.project();
let body = &mut this.body;
tokio::pin!(body);
let ret = futures::ready!(body.poll_data(cx));
let frame = futures::ready!(body.poll_frame(cx));
// If this was the last frame, then drop the handle immediately.
if this.body.is_end_stream() {
drop(this.handle.take());
}
Poll::Ready(ret)
}
fn poll_trailers(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
let this = self.project();
let ret = futures::ready!(this.body.poll_trailers(cx));
// Once trailers are received, the handle is dropped immediately (in case the body
// is retained longer for some reason).
drop(this.handle.take());
Poll::Ready(ret)
Poll::Ready(frame)
}
#[inline]
@ -198,7 +172,7 @@ impl<T: Send + 'static, B: HttpBody> HttpBody for PendingUntilEosBody<T, B> {
mod tests {
use super::{PendingUntilEos, PendingUntilFirstData};
use futures::future::poll_fn;
use hyper::body::HttpBody;
use http_body::{Body, Frame};
use std::collections::VecDeque;
use std::io::Cursor;
use std::pin::Pin;
@ -225,11 +199,13 @@ mod tests {
assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_data(cx)
body.poll_frame(cx)
}))
.poll())
.expect("data some")
.expect("data ok");
.expect("frame is some")
.expect("frame is ok")
.into_data()
.expect("frame is data");
assert!(wk.upgrade().is_none());
}
@ -282,10 +258,10 @@ mod tests {
let res = assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_data(cx)
body.poll_frame(cx)
}))
.poll());
assert!(res.expect("data is some").is_err());
assert!(res.expect("frame is some").is_err());
assert!(wk.upgrade().is_none());
}
@ -308,21 +284,21 @@ mod tests {
assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_data(cx)
body.poll_frame(cx)
}))
.poll())
.expect("data some")
.expect("data ok");
.expect("frame is some")
.expect("frame is ok");
assert!(wk.upgrade().is_some());
assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_data(cx)
body.poll_frame(cx)
}))
.poll())
.expect("data some")
.expect("data ok");
.expect("frame is some")
.expect("frame is ok");
assert!(wk.upgrade().is_none());
}
@ -355,40 +331,42 @@ mod tests {
assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_data(cx)
body.poll_frame(cx)
}))
.poll())
.expect("data")
.expect("data ok");
.expect("frame is some")
.expect("frame is ok");
assert!(wk.upgrade().is_some());
assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_data(cx)
body.poll_frame(cx)
}))
.poll())
.expect("data")
.expect("data ok");
.expect("frame is some")
.expect("frame is ok");
assert!(wk.upgrade().is_some());
assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_frame(cx)
}))
.poll())
.expect("frame is some")
.expect("frame is ok")
.into_trailers()
.expect("is trailers");
assert!(wk.upgrade().is_none());
let poll = assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_data(cx)
body.poll_frame(cx)
}))
.poll());
assert!(poll.is_none());
assert!(wk.upgrade().is_some());
assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_trailers(cx)
}))
.poll())
.expect("trailers ok")
.expect("trailers");
assert!(wk.upgrade().is_none());
}
@ -411,7 +389,7 @@ mod tests {
let poll = assert_ready!(task::spawn(poll_fn(|cx| {
let body = &mut body;
tokio::pin!(body);
body.poll_data(cx)
body.poll_frame(cx)
}))
.poll());
assert!(poll.expect("some").is_err());
@ -429,7 +407,7 @@ mod tests {
#[derive(Default)]
struct TestBody(VecDeque<&'static str>, Option<http::HeaderMap>);
impl HttpBody for TestBody {
impl Body for TestBody {
type Data = Cursor<&'static str>;
type Error = &'static str;
@ -437,26 +415,27 @@ mod tests {
self.0.is_empty() & self.1.is_none()
}
fn poll_data(
fn poll_frame(
mut self: Pin<&mut Self>,
_: &mut Context<'_>,
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
Poll::Ready(self.as_mut().0.pop_front().map(Cursor::new).map(Ok))
}
fn poll_trailers(
mut self: Pin<&mut Self>,
_: &mut Context<'_>,
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
let mut this = self.as_mut();
assert!(this.0.is_empty());
Poll::Ready(Ok(this.1.take()))
// Return the next data frame from the sequence of chunks.
if let Some(chunk) = this.0.pop_front() {
let frame = Some(Ok(Frame::data(Cursor::new(chunk))));
return Poll::Ready(frame);
}
// Yield the trailers once all data frames have been yielded.
let trailers = this.1.take().map(Frame::<Self::Data>::trailers).map(Ok);
Poll::Ready(trailers)
}
}
#[derive(Default)]
struct ErrBody(Option<&'static str>);
impl HttpBody for ErrBody {
impl Body for ErrBody {
type Data = Cursor<&'static str>;
type Error = &'static str;
@ -464,18 +443,13 @@ mod tests {
self.0.is_none()
}
fn poll_data(
fn poll_frame(
mut self: Pin<&mut Self>,
_: &mut Context<'_>,
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
Poll::Ready(Some(Err(self.as_mut().0.take().expect("err"))))
}
) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
let err = self.as_mut().0.take().expect("err");
fn poll_trailers(
mut self: Pin<&mut Self>,
_: &mut Context<'_>,
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
Poll::Ready(Err(self.as_mut().0.take().expect("err")))
Poll::Ready(Some(Err(err)))
}
}
}

View File

@ -15,9 +15,13 @@ toolchain := ""
features := ""
export LINKERD2_PROXY_VERSION := env_var_or_default("LINKERD2_PROXY_VERSION", "0.0.0-dev." + `git rev-parse --short HEAD`)
export LINKERD2_PROXY_VERSION := env_var_or_default("LINKERD2_PROXY_VERSION", "0.0.0-dev" + `git rev-parse --short HEAD`)
export LINKERD2_PROXY_VENDOR := env_var_or_default("LINKERD2_PROXY_VENDOR", `whoami` + "@" + `hostname`)
# TODO: these variables will be included in dev v48
export AWS_LC_SYS_CFLAGS_aarch64_unknown_linux_gnu := env_var_or_default("AWS_LC_SYS_CFLAGS_aarch64_unknown_linux_gnu", "-fuse-ld=/usr/aarch64-linux-gnu/bin/ld")
export AWS_LC_SYS_CFLAGS_aarch64_unknown_linux_musl := env_var_or_default("AWS_LC_SYS_CFLAGS_aarch64_unknown_linux_musl", "-fuse-ld=/usr/aarch64-linux-gnu/bin/ld")
# The version name to use for packages.
package_version := "v" + LINKERD2_PROXY_VERSION
@ -26,28 +30,30 @@ docker-repo := "localhost/linkerd/proxy"
docker-tag := `git rev-parse --abbrev-ref HEAD | sed 's|/|.|g'` + "." + `git rev-parse --short HEAD`
docker-image := docker-repo + ":" + docker-tag
# The architecture name to use for packages. Either 'amd64', 'arm64', or 'arm'.
# The architecture name to use for packages. Either 'amd64' or 'arm64'.
arch := "amd64"
# The OS name to use for packages. Either 'linux' or 'windows'.
os := "linux"
libc := 'gnu'
# If a `arch` is specified, then we change the default cargo `--target`
# to support cross-compilation. Otherwise, we use `rustup` to find the default.
_target := if arch == 'amd64' {
_target := if os + '-' + arch == "linux-amd64" {
"x86_64-unknown-linux-" + libc
} else if arch == "arm64" {
} else if os + '-' + arch == "linux-arm64" {
"aarch64-unknown-linux-" + libc
} else if arch == "arm" {
"armv7-unknown-linux-" + libc + "eabihf"
} else if os + '-' + arch == "windows-amd64" {
"x86_64-pc-windows-" + libc
} else {
error("unsupported arch=" + arch)
error("unsupported: os=" + os + " arch=" + arch + " libc=" + libc)
}
_cargo := 'just-cargo profile=' + profile + ' target=' + _target + ' toolchain=' + toolchain
_target_dir := "target" / _target / profile
_target_bin := _target_dir / "linkerd2-proxy"
_package_name := "linkerd2-proxy-" + package_version + "-" + arch + if libc == 'musl' { '-static' } else { '' }
_target_bin := _target_dir / "linkerd2-proxy" + if os == 'windows' { '.exe' } else { '' }
_package_name := "linkerd2-proxy-" + package_version + "-" + os + "-" + arch + if libc == 'musl' { '-static' } else { '' }
_package_dir := "target/package" / _package_name
shasum := "shasum -a 256"
@ -59,7 +65,7 @@ _features := if features == "all" {
wait-timeout := env_var_or_default("WAIT_TIMEOUT", "1m")
export CXX := 'clang++-14'
export CXX := 'clang++-19'
#
# Recipes
@ -135,7 +141,7 @@ _strip:
_package_bin := _package_dir / "bin" / "linkerd2-proxy"
# XXX {aarch64,arm}-musl builds do not enable PIE, so we use target-specific
# XXX aarch64-musl builds do not enable PIE, so we use target-specific
# files to document those differences.
_expected_checksec := '.checksec' / arch + '-' + libc + '.json'
@ -254,6 +260,12 @@ _tag-set:
_k3d-ready:
@just-k3d ready
export K3D_CLUSTER_NAME := "l5d-proxy"
export K3D_CREATE_FLAGS := "--no-lb"
export K3S_DISABLE := "local-storage,traefik,servicelb,metrics-server@server:*"
k3d-create: && _k3d-ready
@just-k3d create
k3d-load-linkerd: _tag-set _k3d-ready
for i in \
'{{ _controller-image }}:{{ linkerd-tag }}' \
@ -270,6 +282,7 @@ k3d-load-linkerd: _tag-set _k3d-ready
# Install crds on the test cluster.
_linkerd-crds-install: _k3d-ready
{{ _kubectl }} apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
{{ _linkerd }} install --crds \
| {{ _kubectl }} apply -f -
{{ _kubectl }} wait crd --for condition=established \

View File

@ -1,14 +1,14 @@
[package]
name = "linkerd-addr"
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
[dependencies]
http = "0.2"
ipnet = "2.10"
http = { workspace = true }
ipnet = "2.11"
linkerd-dns-name = { path = "../dns/name" }
thiserror = "2"

View File

@ -1,9 +1,10 @@
[package]
name = "linkerd-addr-fuzz"
version = "0.0.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
publish = false
edition = "2021"
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
[package.metadata]
cargo-fuzz = true
@ -12,7 +13,7 @@ cargo-fuzz = true
libfuzzer-sys = "0.4"
linkerd-addr = { path = ".." }
linkerd-tracing = { path = "../../tracing", features = ["ansi"] }
tracing = "0.1"
tracing = { workspace = true }
# Prevent this from interfering with workspaces
[workspace]

View File

@ -100,15 +100,11 @@ impl Addr {
// them ourselves.
format!("[{}]", a.ip())
};
http::uri::Authority::from_str(&ip).unwrap_or_else(|err| {
panic!("SocketAddr ({}) must be valid authority: {}", a, err)
})
}
Addr::Socket(a) => {
http::uri::Authority::from_str(&a.to_string()).unwrap_or_else(|err| {
panic!("SocketAddr ({}) must be valid authority: {}", a, err)
})
http::uri::Authority::from_str(&ip)
.unwrap_or_else(|err| panic!("SocketAddr ({a}) must be valid authority: {err}"))
}
Addr::Socket(a) => http::uri::Authority::from_str(&a.to_string())
.unwrap_or_else(|err| panic!("SocketAddr ({a}) must be valid authority: {err}")),
}
}
@ -265,14 +261,14 @@ mod tests {
];
for (host, expected_result) in cases {
let a = Addr::from_str(host).unwrap();
assert_eq!(a.is_loopback(), *expected_result, "{:?}", host)
assert_eq!(a.is_loopback(), *expected_result, "{host:?}")
}
}
fn test_to_http_authority(cases: &[&str]) {
let width = cases.iter().map(|s| s.len()).max().unwrap_or(0);
for host in cases {
print!("trying {:1$} ... ", host, width);
print!("trying {host:width$} ... ");
Addr::from_str(host).unwrap().to_http_authority();
println!("ok");
}

View File

@ -1,10 +1,10 @@
[package]
name = "linkerd-app"
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
description = """
Configures and executes the proxy
@ -18,6 +18,7 @@ pprof = ["linkerd-app-admin/pprof"]
[dependencies]
futures = { version = "0.3", default-features = false }
hyper-util = { workspace = true }
linkerd-app-admin = { path = "./admin" }
linkerd-app-core = { path = "./core" }
linkerd-app-gateway = { path = "./gateway" }
@ -27,11 +28,12 @@ linkerd-error = { path = "../error" }
linkerd-opencensus = { path = "../opencensus" }
linkerd-opentelemetry = { path = "../opentelemetry" }
linkerd-tonic-stream = { path = "../tonic-stream" }
linkerd-workers = { path = "../workers" }
rangemap = "1"
regex = "1"
thiserror = "2"
tokio = { version = "1", features = ["rt"] }
tokio-stream = { version = "0.1", features = ["time", "sync"] }
tonic = { version = "0.10", default-features = false, features = ["prost"] }
tower = "0.4"
tracing = "0.1"
tonic = { workspace = true, default-features = false, features = ["prost"] }
tower = { workspace = true }
tracing = { workspace = true }

View File

@ -1,10 +1,10 @@
[package]
name = "linkerd-app-admin"
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
description = """
The linkerd proxy's admin server.
"""
@ -15,24 +15,26 @@ pprof = ["deflate", "dep:pprof"]
log-streaming = ["linkerd-tracing/stream"]
[dependencies]
bytes = { workspace = true }
deflate = { version = "1", optional = true, features = ["gzip"] }
http = "0.2"
http-body = "0.4"
hyper = { version = "0.14", features = ["deprecated", "http1", "http2"] }
http = { workspace = true }
http-body = { workspace = true }
http-body-util = { workspace = true }
hyper = { workspace = true, features = ["http1", "http2"] }
futures = { version = "0.3", default-features = false }
pprof = { version = "0.14", optional = true, features = ["prost-codec"] }
pprof = { version = "0.15", optional = true, features = ["prost-codec"] }
serde = "1"
serde_json = "1"
thiserror = "2"
tokio = { version = "1", features = ["macros", "sync", "parking_lot"] }
tracing = "0.1"
tracing = { workspace = true }
linkerd-app-core = { path = "../core" }
linkerd-app-inbound = { path = "../inbound" }
linkerd-tracing = { path = "../../tracing" }
[dependencies.tower]
version = "0.4"
workspace = true
default-features = false
features = [
"buffer",

View File

@ -12,13 +12,9 @@
use futures::future::{self, TryFutureExt};
use http::StatusCode;
use hyper::{
body::{Body, HttpBody},
Request, Response,
};
use linkerd_app_core::{
metrics::{self as metrics, FmtMetrics},
proxy::http::ClientHandle,
metrics::{self as metrics, legacy::FmtMetrics},
proxy::http::{Body, BoxBody, ClientHandle, Request, Response},
trace, Error, Result,
};
use std::{
@ -36,7 +32,7 @@ pub use self::readiness::{Latch, Readiness};
#[derive(Clone)]
pub struct Admin<M> {
metrics: metrics::Serve<M>,
metrics: metrics::legacy::Serve<M>,
tracing: trace::Handle,
ready: Readiness,
shutdown_tx: mpsc::UnboundedSender<()>,
@ -45,7 +41,7 @@ pub struct Admin<M> {
pprof: Option<crate::pprof::Pprof>,
}
pub type ResponseFuture = Pin<Box<dyn Future<Output = Result<Response<Body>>> + Send + 'static>>;
pub type ResponseFuture = Pin<Box<dyn Future<Output = Result<Response<BoxBody>>> + Send + 'static>>;
impl<M> Admin<M> {
pub fn new(
@ -56,7 +52,7 @@ impl<M> Admin<M> {
tracing: trace::Handle,
) -> Self {
Self {
metrics: metrics::Serve::new(metrics),
metrics: metrics::legacy::Serve::new(metrics),
ready,
shutdown_tx,
enable_shutdown,
@ -73,30 +69,30 @@ impl<M> Admin<M> {
self
}
fn ready_rsp(&self) -> Response<Body> {
fn ready_rsp(&self) -> Response<BoxBody> {
if self.ready.is_ready() {
Response::builder()
.status(StatusCode::OK)
.header(http::header::CONTENT_TYPE, "text/plain")
.body("ready\n".into())
.body(BoxBody::from_static("ready\n"))
.expect("builder with known status code must not fail")
} else {
Response::builder()
.status(StatusCode::SERVICE_UNAVAILABLE)
.body("not ready\n".into())
.body(BoxBody::from_static("not ready\n"))
.expect("builder with known status code must not fail")
}
}
fn live_rsp() -> Response<Body> {
fn live_rsp() -> Response<BoxBody> {
Response::builder()
.status(StatusCode::OK)
.header(http::header::CONTENT_TYPE, "text/plain")
.body("live\n".into())
.body(BoxBody::from_static("live\n"))
.expect("builder with known status code must not fail")
}
fn env_rsp<B>(req: Request<B>) -> Response<Body> {
fn env_rsp<B>(req: Request<B>) -> Response<BoxBody> {
use std::{collections::HashMap, env, ffi::OsString};
if req.method() != http::Method::GET {
@ -142,56 +138,58 @@ impl<M> Admin<M> {
json::json_rsp(&env)
}
fn shutdown(&self) -> Response<Body> {
fn shutdown(&self) -> Response<BoxBody> {
if !self.enable_shutdown {
return Response::builder()
.status(StatusCode::NOT_FOUND)
.header(http::header::CONTENT_TYPE, "text/plain")
.body("shutdown endpoint is not enabled\n".into())
.body(BoxBody::from_static("shutdown endpoint is not enabled\n"))
.expect("builder with known status code must not fail");
}
if self.shutdown_tx.send(()).is_ok() {
Response::builder()
.status(StatusCode::OK)
.header(http::header::CONTENT_TYPE, "text/plain")
.body("shutdown\n".into())
.body(BoxBody::from_static("shutdown\n"))
.expect("builder with known status code must not fail")
} else {
Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header(http::header::CONTENT_TYPE, "text/plain")
.body("shutdown listener dropped\n".into())
.body(BoxBody::from_static("shutdown listener dropped\n"))
.expect("builder with known status code must not fail")
}
}
fn internal_error_rsp(error: impl ToString) -> http::Response<Body> {
fn internal_error_rsp(error: impl ToString) -> http::Response<BoxBody> {
http::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.header(http::header::CONTENT_TYPE, "text/plain")
.body(error.to_string().into())
.body(BoxBody::new(error.to_string()))
.expect("builder with known status code should not fail")
}
fn not_found() -> Response<Body> {
fn not_found() -> Response<BoxBody> {
Response::builder()
.status(http::StatusCode::NOT_FOUND)
.body(Body::empty())
.body(BoxBody::empty())
.expect("builder with known status code must not fail")
}
fn method_not_allowed() -> Response<Body> {
fn method_not_allowed() -> Response<BoxBody> {
Response::builder()
.status(http::StatusCode::METHOD_NOT_ALLOWED)
.body(Body::empty())
.body(BoxBody::empty())
.expect("builder with known status code must not fail")
}
fn forbidden_not_localhost() -> Response<Body> {
fn forbidden_not_localhost() -> Response<BoxBody> {
Response::builder()
.status(http::StatusCode::FORBIDDEN)
.header(http::header::CONTENT_TYPE, "text/plain")
.body("Requests are only permitted from localhost.".into())
.body(BoxBody::new::<String>(
"Requests are only permitted from localhost.".into(),
))
.expect("builder with known status code must not fail")
}
@ -215,11 +213,11 @@ impl<M> Admin<M> {
impl<M, B> tower::Service<http::Request<B>> for Admin<M>
where
M: FmtMetrics,
B: HttpBody + Send + 'static,
B: Body + Send + 'static,
B::Error: Into<Error>,
B::Data: Send,
{
type Response = http::Response<Body>;
type Response = http::Response<BoxBody>;
type Error = Error;
type Future = ResponseFuture;
@ -331,7 +329,7 @@ mod tests {
let r = Request::builder()
.method(Method::GET)
.uri("http://0.0.0.0/ready")
.body(Body::empty())
.body(BoxBody::empty())
.unwrap();
let f = admin.clone().oneshot(r);
timeout(TIMEOUT, f).await.expect("timeout").expect("call")

View File

@ -1,14 +1,17 @@
static JSON_MIME: &str = "application/json";
pub(in crate::server) static JSON_HEADER_VAL: HeaderValue = HeaderValue::from_static(JSON_MIME);
use bytes::Bytes;
use hyper::{
header::{self, HeaderValue},
Body, StatusCode,
StatusCode,
};
use linkerd_app_core::proxy::http::BoxBody;
pub(crate) fn json_error_rsp(
error: impl ToString,
status: http::StatusCode,
) -> http::Response<Body> {
) -> http::Response<BoxBody> {
mk_rsp(
status,
&serde_json::json!({
@ -18,11 +21,12 @@ pub(crate) fn json_error_rsp(
)
}
pub(crate) fn json_rsp(val: &impl serde::Serialize) -> http::Response<Body> {
pub(crate) fn json_rsp(val: &impl serde::Serialize) -> http::Response<BoxBody> {
mk_rsp(StatusCode::OK, val)
}
pub(crate) fn accepts_json<B>(req: &http::Request<B>) -> Result<(), http::Response<Body>> {
#[allow(clippy::result_large_err)]
pub(crate) fn accepts_json<B>(req: &http::Request<B>) -> Result<(), http::Response<BoxBody>> {
if let Some(accept) = req.headers().get(header::ACCEPT) {
let accept = match std::str::from_utf8(accept.as_bytes()) {
Ok(accept) => accept,
@ -41,7 +45,7 @@ pub(crate) fn accepts_json<B>(req: &http::Request<B>) -> Result<(), http::Respon
tracing::warn!(?accept, "Accept header will not accept 'application/json'");
return Err(http::Response::builder()
.status(StatusCode::NOT_ACCEPTABLE)
.body(JSON_MIME.into())
.body(BoxBody::from_static(JSON_MIME))
.expect("builder with known status code must not fail"));
}
}
@ -49,18 +53,26 @@ pub(crate) fn accepts_json<B>(req: &http::Request<B>) -> Result<(), http::Respon
Ok(())
}
fn mk_rsp(status: StatusCode, val: &impl serde::Serialize) -> http::Response<Body> {
match serde_json::to_vec(val) {
Ok(json) => http::Response::builder()
fn mk_rsp(status: StatusCode, val: &impl serde::Serialize) -> http::Response<BoxBody> {
// Serialize the value into JSON, and then place the bytes in a boxed response body.
let json = serde_json::to_vec(val)
.map(Bytes::from)
.map(http_body_util::Full::new)
.map(BoxBody::new);
match json {
Ok(body) => http::Response::builder()
.status(status)
.header(header::CONTENT_TYPE, JSON_HEADER_VAL.clone())
.body(json.into())
.body(body)
.expect("builder with known status code must not fail"),
Err(error) => {
tracing::warn!(?error, "failed to serialize JSON value");
http::Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(format!("failed to serialize JSON value: {error}").into())
.body(BoxBody::new(format!(
"failed to serialize JSON value: {error}"
)))
.expect("builder with known status code must not fail")
}
}

View File

@ -1,17 +1,18 @@
use bytes::Buf;
use http::{header, StatusCode};
use hyper::{
body::{Buf, HttpBody},
Body,
use linkerd_app_core::{
proxy::http::{Body, BoxBody},
trace::level,
Error,
};
use linkerd_app_core::{trace::level, Error};
use std::io;
pub async fn serve<B>(
level: level::Handle,
req: http::Request<B>,
) -> Result<http::Response<Body>, Error>
) -> Result<http::Response<BoxBody>, Error>
where
B: HttpBody,
B: Body,
B::Error: Into<Error>,
{
Ok(match *req.method() {
@ -21,14 +22,15 @@ where
}
http::Method::PUT => {
use http_body_util::BodyExt;
let body = req
.into_body()
.collect()
.await
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?
.map_err(io::Error::other)?
.aggregate();
match level.set_from(body.chunk()) {
Ok(_) => mk_rsp(StatusCode::NO_CONTENT, Body::empty()),
Ok(_) => mk_rsp(StatusCode::NO_CONTENT, BoxBody::empty()),
Err(error) => {
tracing::warn!(%error, "Setting log level failed");
mk_rsp(StatusCode::BAD_REQUEST, error)
@ -40,14 +42,19 @@ where
.status(StatusCode::METHOD_NOT_ALLOWED)
.header(header::ALLOW, "GET")
.header(header::ALLOW, "PUT")
.body(Body::empty())
.body(BoxBody::empty())
.expect("builder with known status code must not fail"),
})
}
fn mk_rsp(status: StatusCode, body: impl Into<Body>) -> http::Response<Body> {
fn mk_rsp<B>(status: StatusCode, body: B) -> http::Response<BoxBody>
where
B: Body + Send + 'static,
B::Data: Send + 'static,
B::Error: Into<Error>,
{
http::Response::builder()
.status(status)
.body(body.into())
.body(BoxBody::new(body))
.expect("builder with known status code must not fail")
}

View File

@ -1,10 +1,9 @@
use crate::server::json;
use bytes::{Buf, Bytes};
use futures::FutureExt;
use hyper::{
body::{Buf, Bytes},
header, Body, StatusCode,
};
use hyper::{header, StatusCode};
use linkerd_app_core::{
proxy::http::{Body, BoxBody},
trace::{self},
Error,
};
@ -27,9 +26,9 @@ macro_rules! recover {
pub async fn serve<B>(
handle: trace::Handle,
req: http::Request<B>,
) -> Result<http::Response<Body>, Error>
) -> Result<http::Response<BoxBody>, Error>
where
B: hyper::body::HttpBody,
B: Body,
B::Error: Into<Error>,
{
let handle = handle.into_stream();
@ -52,11 +51,13 @@ where
// If the request is a QUERY, use the request body
method if method.as_str() == "QUERY" => {
// TODO(eliza): validate that the request has a content-length...
use http_body_util::BodyExt;
let body = recover!(
http_body::Body::collect(req.into_body())
req.into_body()
.collect()
.await
.map_err(Into::into)
.map(http_body::Collected::aggregate),
.map(http_body_util::Collected::aggregate),
"Reading log stream request body",
StatusCode::BAD_REQUEST
);
@ -75,7 +76,7 @@ where
.status(StatusCode::METHOD_NOT_ALLOWED)
.header(header::ALLOW, "GET")
.header(header::ALLOW, "QUERY")
.body(Body::empty())
.body(BoxBody::empty())
.expect("builder with known status code must not fail"));
}
};
@ -100,7 +101,7 @@ where
// https://github.com/hawkw/thingbuf/issues/62 would allow us to avoid the
// copy by passing the channel's pooled buffer directly to hyper, and
// returning it to the channel to be reused when hyper is done with it.
let (mut tx, body) = Body::channel();
let (mut tx, body) = http_body_util::channel::Channel::<Bytes, Error>::new(1024);
tokio::spawn(
async move {
// TODO(eliza): we could definitely implement some batching here.
@ -125,7 +126,7 @@ where
}),
);
Ok(mk_rsp(StatusCode::OK, body))
Ok(mk_rsp(StatusCode::OK, BoxBody::new(body)))
}
fn parse_filter(filter_str: &str) -> Result<EnvFilter, impl std::error::Error> {
@ -134,10 +135,10 @@ fn parse_filter(filter_str: &str) -> Result<EnvFilter, impl std::error::Error> {
filter
}
fn mk_rsp(status: StatusCode, body: impl Into<Body>) -> http::Response<Body> {
fn mk_rsp<B>(status: StatusCode, body: B) -> http::Response<B> {
http::Response::builder()
.status(status)
.header(header::CONTENT_TYPE, json::JSON_HEADER_VAL.clone())
.body(body.into())
.body(body)
.expect("builder with known status code must not fail")
}

View File

@ -1,8 +1,8 @@
use linkerd_app_core::{
classify,
config::ServerConfig,
detect, drain, errors, identity,
metrics::{self, FmtMetrics},
drain, errors, identity,
metrics::{self, legacy::FmtMetrics},
proxy::http,
serve,
svc::{self, ExtractParam, InsertParam, Param},
@ -52,7 +52,7 @@ struct Tcp {
#[derive(Clone, Debug)]
struct Http {
tcp: Tcp,
version: http::Version,
version: http::Variant,
}
#[derive(Clone, Debug)]
@ -122,6 +122,7 @@ impl Config {
.push_on_service(http::BoxResponse::layer())
.arc_new_clone_http();
let inbound::DetectMetrics(detect_metrics) = metrics.detect.clone();
let tcp = http
.unlift_new()
.push(http::NewServeHttp::layer({
@ -136,11 +137,11 @@ impl Config {
}))
.push_filter(
|(http, tcp): (
Result<Option<http::Version>, detect::DetectTimeoutError<_>>,
http::Detection,
Tcp,
)| {
match http {
Ok(Some(version)) => Ok(Http { version, tcp }),
http::Detection::Http(version) => Ok(Http { version, tcp }),
// If detection timed out, we can make an educated guess at the proper
// behavior:
// - If the connection was meshed, it was most likely transported over
@ -148,12 +149,12 @@ impl Config {
// - If the connection was unmeshed, it was mostly likely HTTP/1.
// - If we received some unexpected SNI, the client is mostly likely
// confused/stale.
Err(_timeout) => {
http::Detection::ReadTimeout(_timeout) => {
let version = match tcp.tls {
tls::ConditionalServerTls::None(_) => http::Version::Http1,
tls::ConditionalServerTls::None(_) => http::Variant::Http1,
tls::ConditionalServerTls::Some(tls::ServerTls::Established {
..
}) => http::Version::H2,
}) => http::Variant::H2,
tls::ConditionalServerTls::Some(tls::ServerTls::Passthru {
sni,
}) => {
@ -166,7 +167,7 @@ impl Config {
}
// If the connection failed HTTP detection, check if we detected TLS for
// another target. This might indicate that the client is confused/stale.
Ok(None) => match tcp.tls {
http::Detection::NotHttp => match tcp.tls {
tls::ConditionalServerTls::Some(tls::ServerTls::Passthru { sni }) => {
Err(UnexpectedSni(sni, tcp.client).into())
}
@ -177,9 +178,12 @@ impl Config {
)
.arc_new_tcp()
.lift_new_with_target()
.push(detect::NewDetectService::layer(svc::stack::CloneParam::from(
detect::Config::<http::DetectHttp>::from_timeout(DETECT_TIMEOUT),
)))
.push(http::NewDetect::layer(move |tcp: &Tcp| {
http::DetectParams {
read_timeout: DETECT_TIMEOUT,
metrics: detect_metrics.metrics(tcp.policy.server_label())
}
}))
.push(transport::metrics::NewServer::layer(metrics.proxy.transport))
.push_map_target(move |(tls, addrs): (tls::ConditionalServerTls, B::Addrs)| {
Tcp {
@ -210,7 +214,7 @@ impl Config {
impl Param<transport::labels::Key> for Tcp {
fn param(&self) -> transport::labels::Key {
transport::labels::Key::inbound_server(
self.tls.clone(),
self.tls.as_ref().map(|t| t.labels()),
self.addr.into(),
self.policy.server_label(),
)
@ -219,8 +223,8 @@ impl Param<transport::labels::Key> for Tcp {
// === impl Http ===
impl Param<http::Version> for Http {
fn param(&self) -> http::Version {
impl Param<http::Variant> for Http {
fn param(&self) -> http::Variant {
self.version
}
}
@ -268,7 +272,7 @@ impl Param<metrics::ServerLabel> for Http {
impl Param<metrics::EndpointLabels> for Permitted {
fn param(&self) -> metrics::EndpointLabels {
metrics::InboundEndpointLabels {
tls: self.http.tcp.tls.clone(),
tls: self.http.tcp.tls.as_ref().map(|t| t.labels()),
authority: None,
target_addr: self.http.tcp.addr.into(),
policy: self.permit.labels.clone(),

View File

@ -1,10 +1,10 @@
[package]
name = "linkerd-app-core"
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
description = """
Core infrastructure for the proxy application
@ -13,30 +13,23 @@ independently of the inbound and outbound proxy logic.
"""
[dependencies]
bytes = "1"
drain = { version = "0.1", features = ["retain"] }
http = "0.2"
http-body = "0.4"
hyper = { version = "0.14", features = ["deprecated", "http1", "http2"] }
drain = { workspace = true, features = ["retain"] }
http = { workspace = true }
http-body = { workspace = true }
hyper = { workspace = true, features = ["http1", "http2"] }
futures = { version = "0.3", default-features = false }
ipnet = "2.10"
prometheus-client = "0.22"
regex = "1"
serde_json = "1"
ipnet = "2.11"
prometheus-client = { workspace = true }
thiserror = "2"
tokio = { version = "1", features = ["macros", "sync", "parking_lot"] }
tokio-stream = { version = "0.1", features = ["time"] }
tonic = { version = "0.10", default-features = false, features = ["prost"] }
tracing = "0.1"
parking_lot = "0.12"
tonic = { workspace = true, default-features = false, features = ["prost"] }
tracing = { workspace = true }
pin-project = "1"
linkerd-addr = { path = "../../addr" }
linkerd-conditional = { path = "../../conditional" }
linkerd-dns = { path = "../../dns" }
linkerd-detect = { path = "../../detect" }
linkerd-duplex = { path = "../../duplex" }
linkerd-errno = { path = "../../errno" }
linkerd-error = { path = "../../error" }
linkerd-error-respond = { path = "../../error-respond" }
linkerd-exp-backoff = { path = "../../exp-backoff" }
@ -63,6 +56,7 @@ linkerd-proxy-tcp = { path = "../../proxy/tcp" }
linkerd-proxy-transport = { path = "../../proxy/transport" }
linkerd-reconnect = { path = "../../reconnect" }
linkerd-router = { path = "../../router" }
linkerd-rustls = { path = "../../rustls" }
linkerd-service-profiles = { path = "../../service-profiles" }
linkerd-stack = { path = "../../stack" }
linkerd-stack-metrics = { path = "../../stack/metrics" }
@ -74,15 +68,14 @@ linkerd-tls = { path = "../../tls" }
linkerd-trace-context = { path = "../../trace-context" }
[dependencies.tower]
version = "0.4"
workspace = true
default-features = false
features = ["make", "spawn-ready", "timeout", "util", "limit"]
[target.'cfg(target_os = "linux")'.dependencies]
linkerd-system = { path = "../../system" }
[build-dependencies]
semver = "1"
[dev-dependencies]
quickcheck = { version = "1", default-features = false }
bytes = { workspace = true }
http-body-util = { workspace = true }
linkerd-mock-http-body = { path = "../../mock/http-body" }

View File

@ -4,18 +4,18 @@ fn set_env(name: &str, cmd: &mut Command) {
let value = match cmd.output() {
Ok(output) => String::from_utf8(output.stdout).unwrap(),
Err(err) => {
println!("cargo:warning={}", err);
println!("cargo:warning={err}");
"".to_string()
}
};
println!("cargo:rustc-env={}={}", name, value);
println!("cargo:rustc-env={name}={value}");
}
fn version() -> String {
if let Ok(v) = std::env::var("LINKERD2_PROXY_VERSION") {
if !v.is_empty() {
if semver::Version::parse(&v).is_err() {
panic!("LINKERD2_PROXY_VERSION must be semver");
if let Err(err) = semver::Version::parse(&v) {
panic!("LINKERD2_PROXY_VERSION must be semver: version='{v}' error='{err}'");
}
return v;
}

View File

@ -1,5 +1,4 @@
use crate::profiles;
pub use classify::gate;
use linkerd_error::Error;
use linkerd_proxy_client_policy as client_policy;
use linkerd_proxy_http::{classify, HasH2Reason, ResponseTimeoutError};
@ -214,7 +213,7 @@ fn h2_error(err: &Error) -> String {
if let Some(reason) = err.h2_reason() {
// This should output the error code in the same format as the spec,
// for example: PROTOCOL_ERROR
format!("h2({:?})", reason)
format!("h2({reason:?})")
} else {
trace!("classifying found non-h2 error: {:?}", err);
String::from("unclassified")

View File

@ -1,7 +1,7 @@
pub use crate::exp_backoff::ExponentialBackoff;
use crate::{
proxy::http::{self, h1, h2},
svc::{queue, CloneParam, ExtractParam, Param},
proxy::http::{h1, h2},
svc::{queue, ExtractParam, Param},
transport::{DualListenAddr, Keepalive, ListenAddr, UserTimeout},
};
use std::time::Duration;
@ -59,14 +59,6 @@ impl<T> ExtractParam<queue::Timeout, T> for QueueConfig {
}
}
// === impl ProxyConfig ===
impl ProxyConfig {
pub fn detect_http(&self) -> CloneParam<linkerd_detect::Config<http::DetectHttp>> {
linkerd_detect::Config::from_timeout(self.detect_protocol_timeout).into()
}
}
// === impl ServerConfig ===
impl Param<DualListenAddr> for ServerConfig {

View File

@ -69,8 +69,10 @@ impl fmt::Display for ControlAddr {
}
}
pub type RspBody =
linkerd_http_metrics::requests::ResponseBody<http::balance::Body<hyper::Body>, classify::Eos>;
pub type RspBody = linkerd_http_metrics::requests::ResponseBody<
http::balance::Body<hyper::body::Incoming>,
classify::Eos,
>;
#[derive(Clone, Debug, Default)]
pub struct Metrics {
@ -99,7 +101,7 @@ impl Config {
identity: identity::NewClient,
) -> svc::ArcNewService<
(),
svc::BoxCloneSyncService<http::Request<tonic::body::BoxBody>, http::Response<RspBody>>,
svc::BoxCloneSyncService<http::Request<tonic::body::Body>, http::Response<RspBody>>,
> {
let addr = self.addr;
tracing::trace!(%addr, "Building");
@ -112,7 +114,7 @@ impl Config {
warn!(error, "Failed to resolve control-plane component");
if let Some(e) = crate::errors::cause_ref::<dns::ResolveError>(&*error) {
if let Some(ttl) = e.negative_ttl() {
return Ok(Either::Left(
return Ok::<_, Error>(Either::Left(
IntervalStream::new(time::interval(ttl)).map(|_| ()),
));
}
@ -129,9 +131,9 @@ impl Config {
self.connect.user_timeout,
))
.push(tls::Client::layer(identity))
.push_connect_timeout(self.connect.timeout)
.push_connect_timeout(self.connect.timeout) // Client<NewClient, ConnectTcp>
.push_map_target(|(_version, target)| target)
.push(self::client::layer(self.connect.http2))
.push(self::client::layer::<_, _>(self.connect.http2))
.push_on_service(svc::MapErr::layer_boxed())
.into_new_service();

View File

@ -1,25 +1,50 @@
pub use linkerd_dns::*;
use std::path::PathBuf;
use self::metrics::Labels;
use linkerd_metrics::prom::{Counter, Family, Registry};
use std::time::Duration;
pub use linkerd_dns::*;
mod metrics;
#[derive(Clone, Debug)]
pub struct Config {
pub min_ttl: Option<Duration>,
pub max_ttl: Option<Duration>,
pub resolv_conf_path: PathBuf,
}
pub struct Dns {
pub resolver: Resolver,
resolver: Resolver,
resolutions: Family<Labels, Counter>,
}
// === impl Dns ===
impl Dns {
/// Returns a new [`Resolver`].
pub fn resolver(&self, client: &'static str) -> Resolver {
let metrics = self.metrics(client);
self.resolver.clone().with_metrics(metrics)
}
}
// === impl Config ===
impl Config {
pub fn build(self) -> Dns {
pub fn build(self, registry: &mut Registry) -> Dns {
let resolutions = Family::default();
registry.register(
"resolutions",
"Counts the number of DNS records that have been resolved.",
resolutions.clone(),
);
let resolver =
Resolver::from_system_config_with(&self).expect("system DNS config must be valid");
Dns { resolver }
Dns {
resolver,
resolutions,
}
}
}

View File

@ -0,0 +1,115 @@
use super::{Dns, Metrics};
use linkerd_metrics::prom::encoding::{
EncodeLabel, EncodeLabelSet, EncodeLabelValue, LabelSetEncoder, LabelValueEncoder,
};
use std::fmt::{Display, Write};
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(super) struct Labels {
client: &'static str,
record_type: RecordType,
result: Outcome,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
enum RecordType {
A,
Srv,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
enum Outcome {
Ok,
NotFound,
}
// === impl Dns ===
impl Dns {
pub(super) fn metrics(&self, client: &'static str) -> Metrics {
let family = &self.resolutions;
let a_records_resolved = (*family.get_or_create(&Labels {
client,
record_type: RecordType::A,
result: Outcome::Ok,
}))
.clone();
let a_records_not_found = (*family.get_or_create(&Labels {
client,
record_type: RecordType::A,
result: Outcome::NotFound,
}))
.clone();
let srv_records_resolved = (*family.get_or_create(&Labels {
client,
record_type: RecordType::Srv,
result: Outcome::Ok,
}))
.clone();
let srv_records_not_found = (*family.get_or_create(&Labels {
client,
record_type: RecordType::Srv,
result: Outcome::NotFound,
}))
.clone();
Metrics {
a_records_resolved,
a_records_not_found,
srv_records_resolved,
srv_records_not_found,
}
}
}
// === impl Labels ===
impl EncodeLabelSet for Labels {
fn encode(&self, mut encoder: LabelSetEncoder<'_>) -> Result<(), std::fmt::Error> {
let Self {
client,
record_type,
result,
} = self;
("client", *client).encode(encoder.encode_label())?;
("record_type", record_type).encode(encoder.encode_label())?;
("result", result).encode(encoder.encode_label())?;
Ok(())
}
}
// === impl Outcome ===
impl EncodeLabelValue for &Outcome {
fn encode(&self, encoder: &mut LabelValueEncoder<'_>) -> Result<(), std::fmt::Error> {
encoder.write_str(self.to_string().as_str())
}
}
impl Display for Outcome {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Ok => "ok",
Self::NotFound => "not_found",
})
}
}
// === impl RecordType ===
impl EncodeLabelValue for &RecordType {
fn encode(&self, encoder: &mut LabelValueEncoder<'_>) -> Result<(), std::fmt::Error> {
encoder.write_str(self.to_string().as_str())
}
}
impl Display for RecordType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::A => "A/AAAA",
Self::Srv => "SRV",
})
}
}

View File

@ -1,3 +1,4 @@
pub mod body;
pub mod respond;
pub use self::respond::{HttpRescue, NewRespond, NewRespondService, SyntheticHttpResponse};
@ -6,6 +7,16 @@ pub use linkerd_proxy_http::h2::H2Error;
pub use linkerd_stack::{FailFastError, LoadShedError};
pub use tonic::Code as Grpc;
/// Header names and values related to error responses.
pub mod header {
use http::header::{HeaderName, HeaderValue};
pub const L5D_PROXY_CONNECTION: HeaderName = HeaderName::from_static("l5d-proxy-connection");
pub const L5D_PROXY_ERROR: HeaderName = HeaderName::from_static("l5d-proxy-error");
pub(super) const GRPC_CONTENT_TYPE: HeaderValue = HeaderValue::from_static("application/grpc");
pub(super) const GRPC_MESSAGE: HeaderName = HeaderName::from_static("grpc-message");
pub(super) const GRPC_STATUS: HeaderName = HeaderName::from_static("grpc-status");
}
#[derive(Debug, thiserror::Error)]
#[error("connect timed out after {0:?}")]
pub struct ConnectTimeout(pub(crate) std::time::Duration);
@ -18,3 +29,27 @@ pub fn has_grpc_status(error: &crate::Error, code: tonic::Code) -> bool {
.map(|s| s.code() == code)
.unwrap_or(false)
}
// Copied from tonic, where it's private.
fn code_header(code: tonic::Code) -> http::HeaderValue {
use {http::HeaderValue, tonic::Code};
match code {
Code::Ok => HeaderValue::from_static("0"),
Code::Cancelled => HeaderValue::from_static("1"),
Code::Unknown => HeaderValue::from_static("2"),
Code::InvalidArgument => HeaderValue::from_static("3"),
Code::DeadlineExceeded => HeaderValue::from_static("4"),
Code::NotFound => HeaderValue::from_static("5"),
Code::AlreadyExists => HeaderValue::from_static("6"),
Code::PermissionDenied => HeaderValue::from_static("7"),
Code::ResourceExhausted => HeaderValue::from_static("8"),
Code::FailedPrecondition => HeaderValue::from_static("9"),
Code::Aborted => HeaderValue::from_static("10"),
Code::OutOfRange => HeaderValue::from_static("11"),
Code::Unimplemented => HeaderValue::from_static("12"),
Code::Internal => HeaderValue::from_static("13"),
Code::Unavailable => HeaderValue::from_static("14"),
Code::DataLoss => HeaderValue::from_static("15"),
Code::Unauthenticated => HeaderValue::from_static("16"),
}
}

View File

@ -0,0 +1,314 @@
use super::{
header::{GRPC_MESSAGE, GRPC_STATUS},
respond::{HttpRescue, SyntheticHttpResponse},
};
use http::header::HeaderValue;
use http_body::Frame;
use linkerd_error::{Error, Result};
use pin_project::pin_project;
use std::{
pin::Pin,
task::{Context, Poll},
};
use tracing::{debug, warn};
/// Returns a "gRPC rescue" body.
///
/// This returns a body that, should the inner `B`-typed body return an error when polling for
/// DATA frames, will "rescue" the stream and return a TRAILERS frame that describes the error.
#[pin_project(project = ResponseBodyProj)]
pub struct ResponseBody<R, B>(#[pin] Inner<R, B>);
#[pin_project(project = InnerProj)]
enum Inner<R, B> {
/// An inert body that delegates directly down to the underlying body `B`.
Passthru(#[pin] B),
/// A body that will be rescued if it yields an error.
GrpcRescue {
#[pin]
inner: B,
/// An error response [strategy][HttpRescue].
rescue: R,
emit_headers: bool,
},
/// The underlying body `B` yielded an error and was "rescued".
Rescued,
}
// === impl ResponseBody ===
impl<R, B> ResponseBody<R, B> {
/// Returns a body in "passthru" mode.
pub fn passthru(inner: B) -> Self {
Self(Inner::Passthru(inner))
}
/// Returns a "gRPC rescue" body.
pub fn grpc_rescue(inner: B, rescue: R, emit_headers: bool) -> Self {
Self(Inner::GrpcRescue {
inner,
rescue,
emit_headers,
})
}
}
impl<R, B: Default + linkerd_proxy_http::Body> Default for ResponseBody<R, B> {
fn default() -> Self {
Self(Inner::Passthru(B::default()))
}
}
impl<R, B> linkerd_proxy_http::Body for ResponseBody<R, B>
where
B: linkerd_proxy_http::Body<Error = Error>,
R: HttpRescue<B::Error>,
{
type Data = B::Data;
type Error = B::Error;
fn poll_frame(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<std::result::Result<http_body::Frame<Self::Data>, Self::Error>>> {
let ResponseBodyProj(inner) = self.as_mut().project();
match inner.project() {
InnerProj::Passthru(inner) => inner.poll_frame(cx),
InnerProj::GrpcRescue {
inner,
rescue,
emit_headers,
} => match inner.poll_frame(cx) {
Poll::Ready(Some(Err(error))) => {
// The inner body has yielded an error, which we will try to rescue. If so,
// yield synthetic trailers reporting the error.
let trailers = Self::rescue(error, rescue, *emit_headers)?;
self.set(Self(Inner::Rescued));
Poll::Ready(Some(Ok(Frame::trailers(trailers))))
}
poll => poll,
},
InnerProj::Rescued => Poll::Ready(None),
}
}
#[inline]
fn is_end_stream(&self) -> bool {
let Self(inner) = self;
match inner {
Inner::Passthru(inner) => inner.is_end_stream(),
Inner::GrpcRescue { inner, .. } => inner.is_end_stream(),
Inner::Rescued => true,
}
}
#[inline]
fn size_hint(&self) -> http_body::SizeHint {
let Self(inner) = self;
match inner {
Inner::Passthru(inner) => inner.size_hint(),
Inner::GrpcRescue { inner, .. } => inner.size_hint(),
Inner::Rescued => http_body::SizeHint::with_exact(0),
}
}
}
impl<R, B> ResponseBody<R, B>
where
B: http_body::Body,
R: HttpRescue<B::Error>,
{
/// Maps an error yielded by the inner body to a collection of gRPC trailers.
///
/// This function returns `Ok(trailers)` if the given [`HttpRescue<E>`] strategy could identify
/// a cause for an error yielded by the inner `B`-typed body.
fn rescue(
error: B::Error,
rescue: &R,
emit_headers: bool,
) -> Result<http::HeaderMap, B::Error> {
let SyntheticHttpResponse {
grpc_status,
message,
..
} = rescue.rescue(error)?;
debug!(grpc.status = ?grpc_status, "Synthesizing gRPC trailers");
let mut t = http::HeaderMap::new();
t.insert(GRPC_STATUS, super::code_header(grpc_status));
if emit_headers {
// A gRPC message trailer is only included if instructed to emit additional headers.
t.insert(
GRPC_MESSAGE,
HeaderValue::from_str(&message).unwrap_or_else(|error| {
warn!(%error, "Failed to encode error header");
HeaderValue::from_static("Unexpected error")
}),
);
}
Ok(t)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::errors::header::{GRPC_MESSAGE, GRPC_STATUS};
use http::HeaderMap;
use linkerd_mock_http_body::MockBody;
struct MockRescue;
impl<E> HttpRescue<E> for MockRescue {
/// Attempts to synthesize a response from the given error.
fn rescue(&self, _: E) -> Result<SyntheticHttpResponse, E> {
let synthetic = SyntheticHttpResponse::internal_error("MockRescue::rescue");
Ok(synthetic)
}
}
#[tokio::test]
async fn rescue_body_recovers_from_error_without_grpc_message() {
let (_guard, _handle) = linkerd_tracing::test::trace_init();
let trailers = {
let mut trls = HeaderMap::with_capacity(1);
let value = HeaderValue::from_static("caboose");
trls.insert("trailer", value);
trls
};
let rescue = {
let inner = MockBody::default()
.then_yield_data(Poll::Ready(Some(Ok("inter".into()))))
.then_yield_data(Poll::Ready(Some(Err("an error midstream".into()))))
.then_yield_data(Poll::Ready(Some(Ok("rupted".into()))))
.then_yield_trailer(Poll::Ready(Some(Ok(trailers))));
let rescue = MockRescue;
let emit_headers = false;
ResponseBody::grpc_rescue(inner, rescue, emit_headers)
};
let (data, Some(trailers)) = body_to_string(rescue).await else {
panic!("trailers should exist");
};
assert_eq!(data, "inter");
assert_eq!(
trailers[GRPC_STATUS],
i32::from(tonic::Code::Internal).to_string()
);
assert_eq!(trailers.get(GRPC_MESSAGE), None);
}
#[tokio::test]
async fn rescue_body_recovers_from_error_emitting_message() {
let (_guard, _handle) = linkerd_tracing::test::trace_init();
let trailers = {
let mut trls = HeaderMap::with_capacity(1);
let value = HeaderValue::from_static("caboose");
trls.insert("trailer", value);
trls
};
let rescue = {
let inner = MockBody::default()
.then_yield_data(Poll::Ready(Some(Ok("inter".into()))))
.then_yield_data(Poll::Ready(Some(Err("an error midstream".into()))))
.then_yield_data(Poll::Ready(Some(Ok("rupted".into()))))
.then_yield_trailer(Poll::Ready(Some(Ok(trailers))));
let rescue = MockRescue;
let emit_headers = true;
ResponseBody::grpc_rescue(inner, rescue, emit_headers)
};
let (data, Some(trailers)) = body_to_string(rescue).await else {
panic!("trailers should exist");
};
assert_eq!(data, "inter");
assert_eq!(
trailers[GRPC_STATUS],
i32::from(tonic::Code::Internal).to_string()
);
assert_eq!(trailers[GRPC_MESSAGE], "MockRescue::rescue");
}
#[tokio::test]
async fn rescue_body_works_for_empty() {
let (_guard, _handle) = linkerd_tracing::test::trace_init();
let rescue = {
let inner = MockBody::default();
let rescue = MockRescue;
let emit_headers = false;
ResponseBody::grpc_rescue(inner, rescue, emit_headers)
};
let (data, trailers) = body_to_string(rescue).await;
assert_eq!(data, "");
assert_eq!(trailers, None);
}
#[tokio::test]
async fn rescue_body_works_for_body_with_data() {
let (_guard, _handle) = linkerd_tracing::test::trace_init();
let rescue = {
let inner = MockBody::default().then_yield_data(Poll::Ready(Some(Ok("unary".into()))));
let rescue = MockRescue;
let emit_headers = false;
ResponseBody::grpc_rescue(inner, rescue, emit_headers)
};
let (data, trailers) = body_to_string(rescue).await;
assert_eq!(data, "unary");
assert_eq!(trailers, None);
}
#[tokio::test]
async fn rescue_body_works_for_body_with_trailers() {
let (_guard, _handle) = linkerd_tracing::test::trace_init();
let trailers = {
let mut trls = HeaderMap::with_capacity(1);
let value = HeaderValue::from_static("caboose");
trls.insert("trailer", value);
trls
};
let rescue = {
let inner = MockBody::default().then_yield_trailer(Poll::Ready(Some(Ok(trailers))));
let rescue = MockRescue;
let emit_headers = false;
ResponseBody::grpc_rescue(inner, rescue, emit_headers)
};
let (data, trailers) = body_to_string(rescue).await;
assert_eq!(data, "");
assert_eq!(trailers.expect("has trailers")["trailer"], "caboose");
}
async fn body_to_string<B>(mut body: B) -> (String, Option<HeaderMap>)
where
B: http_body::Body + Unpin,
B::Error: std::fmt::Debug,
{
use http_body_util::BodyExt;
let mut data = String::new();
let mut trailers = None;
// Continue reading frames from the body until it is finished.
while let Some(frame) = body
.frame()
.await
.transpose()
.expect("reading a frame succeeds")
{
match frame.into_data().map(|mut buf| {
use bytes::Buf;
let bytes = buf.copy_to_bytes(buf.remaining());
String::from_utf8(bytes.to_vec()).unwrap()
}) {
Ok(ref s) => data.push_str(s),
Err(frame) => {
let trls = frame
.into_trailers()
.map_err(drop)
.expect("test frame is either data or trailers");
trailers = Some(trls);
}
}
}
tracing::info!(?data, ?trailers, "finished reading body");
(data, trailers)
}
}

View File

@ -1,21 +1,16 @@
use super::{
body::ResponseBody,
header::{GRPC_CONTENT_TYPE, GRPC_MESSAGE, GRPC_STATUS, L5D_PROXY_CONNECTION, L5D_PROXY_ERROR},
};
use crate::svc;
use http::header::{HeaderValue, LOCATION};
use linkerd_error::{Error, Result};
use linkerd_error_respond as respond;
use linkerd_proxy_http::orig_proto;
pub use linkerd_proxy_http::{ClientHandle, HasH2Reason};
use linkerd_proxy_http::{orig_proto, ClientHandle};
use linkerd_stack::ExtractParam;
use pin_project::pin_project;
use std::{
borrow::Cow,
pin::Pin,
task::{Context, Poll},
};
use std::borrow::Cow;
use tracing::{debug, info_span, warn};
pub const L5D_PROXY_CONNECTION: &str = "l5d-proxy-connection";
pub const L5D_PROXY_ERROR: &str = "l5d-proxy-error";
pub fn layer<R, P: Clone, N>(
params: P,
) -> impl svc::layer::Layer<N, Service = NewRespondService<R, P, N>> + Clone {
@ -33,10 +28,10 @@ pub trait HttpRescue<E> {
#[derive(Clone, Debug)]
pub struct SyntheticHttpResponse {
grpc_status: tonic::Code,
pub grpc_status: tonic::Code,
http_status: http::StatusCode,
close_connection: bool,
message: Cow<'static, str>,
pub message: Cow<'static, str>,
location: Option<HeaderValue>,
}
@ -62,22 +57,6 @@ pub struct Respond<R> {
emit_headers: bool,
}
#[pin_project(project = ResponseBodyProj)]
pub enum ResponseBody<R, B> {
Passthru(#[pin] B),
GrpcRescue {
#[pin]
inner: B,
trailers: Option<http::HeaderMap>,
rescue: R,
emit_headers: bool,
},
}
const GRPC_CONTENT_TYPE: &str = "application/grpc";
const GRPC_STATUS: &str = "grpc-status";
const GRPC_MESSAGE: &str = "grpc-message";
// === impl HttpRescue ===
impl<E, F> HttpRescue<E> for F
@ -247,7 +226,7 @@ impl SyntheticHttpResponse {
.version(http::Version::HTTP_2)
.header(http::header::CONTENT_LENGTH, "0")
.header(http::header::CONTENT_TYPE, GRPC_CONTENT_TYPE)
.header(GRPC_STATUS, code_header(self.grpc_status));
.header(GRPC_STATUS, super::code_header(self.grpc_status));
if emit_headers {
rsp = rsp
@ -346,7 +325,15 @@ where
let is_grpc = req
.headers()
.get(http::header::CONTENT_TYPE)
.and_then(|v| v.to_str().ok().map(|s| s.starts_with(GRPC_CONTENT_TYPE)))
.and_then(|v| {
v.to_str().ok().map(|s| {
s.starts_with(
GRPC_CONTENT_TYPE
.to_str()
.expect("GRPC_CONTENT_TYPE only contains visible ASCII"),
)
})
})
.unwrap_or(false);
Respond {
client,
@ -388,7 +375,7 @@ impl<R> Respond<R> {
impl<B, R> respond::Respond<http::Response<B>, Error> for Respond<R>
where
B: Default + hyper::body::HttpBody,
B: Default + linkerd_proxy_http::Body,
R: HttpRescue<Error> + Clone,
{
type Response = http::Response<ResponseBody<R, B>>;
@ -396,19 +383,14 @@ where
fn respond(&self, res: Result<http::Response<B>>) -> Result<Self::Response> {
let error = match res {
Ok(rsp) => {
return Ok(rsp.map(|b| match self {
return Ok(rsp.map(|inner| match self {
Respond {
is_grpc: true,
rescue,
emit_headers,
..
} => ResponseBody::GrpcRescue {
inner: b,
trailers: None,
rescue: rescue.clone(),
emit_headers: *emit_headers,
},
_ => ResponseBody::Passthru(b),
} => ResponseBody::grpc_rescue(inner, rescue.clone(), *emit_headers),
_ => ResponseBody::passthru(inner),
}));
}
Err(error) => error,
@ -441,127 +423,3 @@ where
Ok(rsp)
}
}
// === impl ResponseBody ===
impl<R, B: Default + hyper::body::HttpBody> Default for ResponseBody<R, B> {
fn default() -> Self {
ResponseBody::Passthru(B::default())
}
}
impl<R, B> hyper::body::HttpBody for ResponseBody<R, B>
where
B: hyper::body::HttpBody<Error = Error>,
R: HttpRescue<B::Error>,
{
type Data = B::Data;
type Error = B::Error;
fn poll_data(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
match self.project() {
ResponseBodyProj::Passthru(inner) => inner.poll_data(cx),
ResponseBodyProj::GrpcRescue {
inner,
trailers,
rescue,
emit_headers,
} => {
// should not be calling poll_data if we have set trailers derived from an error
assert!(trailers.is_none());
match inner.poll_data(cx) {
Poll::Ready(Some(Err(error))) => {
let SyntheticHttpResponse {
grpc_status,
message,
..
} = rescue.rescue(error)?;
let t = Self::grpc_trailers(grpc_status, &message, *emit_headers);
*trailers = Some(t);
Poll::Ready(None)
}
data => data,
}
}
}
}
#[inline]
fn poll_trailers(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
match self.project() {
ResponseBodyProj::Passthru(inner) => inner.poll_trailers(cx),
ResponseBodyProj::GrpcRescue {
inner, trailers, ..
} => match trailers.take() {
Some(t) => Poll::Ready(Ok(Some(t))),
None => inner.poll_trailers(cx),
},
}
}
#[inline]
fn is_end_stream(&self) -> bool {
match self {
Self::Passthru(inner) => inner.is_end_stream(),
Self::GrpcRescue {
inner, trailers, ..
} => trailers.is_none() && inner.is_end_stream(),
}
}
#[inline]
fn size_hint(&self) -> http_body::SizeHint {
match self {
Self::Passthru(inner) => inner.size_hint(),
Self::GrpcRescue { inner, .. } => inner.size_hint(),
}
}
}
impl<R, B> ResponseBody<R, B> {
fn grpc_trailers(code: tonic::Code, message: &str, emit_headers: bool) -> http::HeaderMap {
debug!(grpc.status = ?code, "Synthesizing gRPC trailers");
let mut t = http::HeaderMap::new();
t.insert(GRPC_STATUS, code_header(code));
if emit_headers {
t.insert(
GRPC_MESSAGE,
HeaderValue::from_str(message).unwrap_or_else(|error| {
warn!(%error, "Failed to encode error header");
HeaderValue::from_static("Unexpected error")
}),
);
}
t
}
}
// Copied from tonic, where it's private.
fn code_header(code: tonic::Code) -> HeaderValue {
use tonic::Code;
match code {
Code::Ok => HeaderValue::from_static("0"),
Code::Cancelled => HeaderValue::from_static("1"),
Code::Unknown => HeaderValue::from_static("2"),
Code::InvalidArgument => HeaderValue::from_static("3"),
Code::DeadlineExceeded => HeaderValue::from_static("4"),
Code::NotFound => HeaderValue::from_static("5"),
Code::AlreadyExists => HeaderValue::from_static("6"),
Code::PermissionDenied => HeaderValue::from_static("7"),
Code::ResourceExhausted => HeaderValue::from_static("8"),
Code::FailedPrecondition => HeaderValue::from_static("9"),
Code::Aborted => HeaderValue::from_static("10"),
Code::OutOfRange => HeaderValue::from_static("11"),
Code::Unimplemented => HeaderValue::from_static("12"),
Code::Internal => HeaderValue::from_static("13"),
Code::Unavailable => HeaderValue::from_static("14"),
Code::DataLoss => HeaderValue::from_static("15"),
Code::Unauthenticated => HeaderValue::from_static("16"),
}
}

View File

@ -25,6 +25,7 @@ pub mod metrics;
pub mod proxy;
pub mod serve;
pub mod svc;
pub mod tls_info;
pub mod transport;
pub use self::build_info::{BuildInfo, BUILD_INFO};
@ -32,7 +33,6 @@ pub use drain;
pub use ipnet::{IpNet, Ipv4Net, Ipv6Net};
pub use linkerd_addr::{self as addr, Addr, AddrMatch, IpMatch, NameAddr, NameMatch};
pub use linkerd_conditional::Conditional;
pub use linkerd_detect as detect;
pub use linkerd_dns;
pub use linkerd_error::{cause_ref, is_caused_by, Error, Infallible, Recover, Result};
pub use linkerd_exp_backoff as exp_backoff;

View File

@ -15,7 +15,7 @@ use crate::{
use linkerd_addr::Addr;
pub use linkerd_metrics::*;
use linkerd_proxy_server_policy as policy;
use prometheus_client::encoding::EncodeLabelValue;
use prometheus_client::encoding::{EncodeLabelSet, EncodeLabelValue};
use std::{
fmt::{self, Write},
net::SocketAddr,
@ -54,7 +54,7 @@ pub struct Proxy {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ControlLabels {
addr: Addr,
server_id: tls::ConditionalClientTls,
server_id: tls::ConditionalClientTlsLabels,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@ -65,7 +65,7 @@ pub enum EndpointLabels {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct InboundEndpointLabels {
pub tls: tls::ConditionalServerTls,
pub tls: tls::ConditionalServerTlsLabels,
pub authority: Option<http::uri::Authority>,
pub target_addr: SocketAddr,
pub policy: RouteAuthzLabels,
@ -73,7 +73,7 @@ pub struct InboundEndpointLabels {
/// A label referencing an inbound `Server` (i.e. for policy).
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ServerLabel(pub Arc<policy::Meta>);
pub struct ServerLabel(pub Arc<policy::Meta>, pub u16);
/// Labels referencing an inbound server and authorization.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
@ -98,7 +98,7 @@ pub struct RouteAuthzLabels {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct OutboundEndpointLabels {
pub server_id: tls::ConditionalClientTls,
pub server_id: tls::ConditionalClientTlsLabels,
pub authority: Option<http::uri::Authority>,
pub labels: Option<String>,
pub zone_locality: OutboundZoneLocality,
@ -155,10 +155,10 @@ where
I: Iterator<Item = (&'i String, &'i String)>,
{
let (k0, v0) = labels_iter.next()?;
let mut out = format!("{}_{}=\"{}\"", prefix, k0, v0);
let mut out = format!("{prefix}_{k0}=\"{v0}\"");
for (k, v) in labels_iter {
write!(out, ",{}_{}=\"{}\"", prefix, k, v).expect("label concat must succeed");
write!(out, ",{prefix}_{k}=\"{v}\"").expect("label concat must succeed");
}
Some(out)
}
@ -166,7 +166,7 @@ where
// === impl Metrics ===
impl Metrics {
pub fn new(retain_idle: Duration) -> (Self, impl FmtMetrics + Clone + Send + 'static) {
pub fn new(retain_idle: Duration) -> (Self, impl legacy::FmtMetrics + Clone + Send + 'static) {
let (control, control_report) = {
let m = http_metrics::Requests::<ControlLabels, Class>::default();
let r = m.clone().into_report(retain_idle).with_prefix("control");
@ -223,6 +223,7 @@ impl Metrics {
opentelemetry,
};
use legacy::FmtMetrics as _;
let report = endpoint_report
.and_report(profile_route_report)
.and_report(retry_report)
@ -243,15 +244,17 @@ impl svc::Param<ControlLabels> for control::ControlAddr {
fn param(&self) -> ControlLabels {
ControlLabels {
addr: self.addr.clone(),
server_id: self.identity.clone(),
server_id: self.identity.as_ref().map(tls::ClientTls::labels),
}
}
}
impl FmtLabels for ControlLabels {
impl legacy::FmtLabels for ControlLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "addr=\"{}\",", self.addr)?;
TlsConnect::from(&self.server_id).fmt_labels(f)?;
let Self { addr, server_id } = self;
write!(f, "addr=\"{addr}\",")?;
TlsConnect::from(server_id).fmt_labels(f)?;
Ok(())
}
@ -279,13 +282,19 @@ impl ProfileRouteLabels {
}
}
impl FmtLabels for ProfileRouteLabels {
impl legacy::FmtLabels for ProfileRouteLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.direction.fmt_labels(f)?;
write!(f, ",dst=\"{}\"", self.addr)?;
let Self {
direction,
addr,
labels,
} = self;
if let Some(labels) = self.labels.as_ref() {
write!(f, ",{}", labels)?;
direction.fmt_labels(f)?;
write!(f, ",dst=\"{addr}\"")?;
if let Some(labels) = labels.as_ref() {
write!(f, ",{labels}")?;
}
Ok(())
@ -306,7 +315,7 @@ impl From<OutboundEndpointLabels> for EndpointLabels {
}
}
impl FmtLabels for EndpointLabels {
impl legacy::FmtLabels for EndpointLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Inbound(i) => (Direction::In, i).fmt_labels(f),
@ -315,70 +324,98 @@ impl FmtLabels for EndpointLabels {
}
}
impl FmtLabels for InboundEndpointLabels {
impl legacy::FmtLabels for InboundEndpointLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(a) = self.authority.as_ref() {
let Self {
tls,
authority,
target_addr,
policy,
} = self;
if let Some(a) = authority.as_ref() {
Authority(a).fmt_labels(f)?;
write!(f, ",")?;
}
(
(TargetAddr(self.target_addr), TlsAccept::from(&self.tls)),
&self.policy,
)
.fmt_labels(f)?;
((TargetAddr(*target_addr), TlsAccept::from(tls)), policy).fmt_labels(f)?;
Ok(())
}
}
impl FmtLabels for ServerLabel {
impl legacy::FmtLabels for ServerLabel {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self(meta, port) = self;
write!(
f,
"srv_group=\"{}\",srv_kind=\"{}\",srv_name=\"{}\"",
self.0.group(),
self.0.kind(),
self.0.name()
"srv_group=\"{}\",srv_kind=\"{}\",srv_name=\"{}\",srv_port=\"{}\"",
meta.group(),
meta.kind(),
meta.name(),
port
)
}
}
impl FmtLabels for ServerAuthzLabels {
impl EncodeLabelSet for ServerLabel {
fn encode(&self, mut enc: prometheus_client::encoding::LabelSetEncoder<'_>) -> fmt::Result {
prom::EncodeLabelSetMut::encode_label_set(self, &mut enc)
}
}
impl prom::EncodeLabelSetMut for ServerLabel {
fn encode_label_set(&self, enc: &mut prom::encoding::LabelSetEncoder<'_>) -> fmt::Result {
use prometheus_client::encoding::EncodeLabel;
("srv_group", self.0.group()).encode(enc.encode_label())?;
("srv_kind", self.0.kind()).encode(enc.encode_label())?;
("srv_name", self.0.name()).encode(enc.encode_label())?;
("srv_port", self.1).encode(enc.encode_label())?;
Ok(())
}
}
impl legacy::FmtLabels for ServerAuthzLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.server.fmt_labels(f)?;
let Self { server, authz } = self;
server.fmt_labels(f)?;
write!(
f,
",authz_group=\"{}\",authz_kind=\"{}\",authz_name=\"{}\"",
self.authz.group(),
self.authz.kind(),
self.authz.name()
authz.group(),
authz.kind(),
authz.name()
)
}
}
impl FmtLabels for RouteLabels {
impl legacy::FmtLabels for RouteLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.server.fmt_labels(f)?;
let Self { server, route } = self;
server.fmt_labels(f)?;
write!(
f,
",route_group=\"{}\",route_kind=\"{}\",route_name=\"{}\"",
self.route.group(),
self.route.kind(),
self.route.name(),
route.group(),
route.kind(),
route.name(),
)
}
}
impl FmtLabels for RouteAuthzLabels {
impl legacy::FmtLabels for RouteAuthzLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.route.fmt_labels(f)?;
let Self { route, authz } = self;
route.fmt_labels(f)?;
write!(
f,
",authz_group=\"{}\",authz_kind=\"{}\",authz_name=\"{}\"",
self.authz.group(),
self.authz.kind(),
self.authz.name(),
authz.group(),
authz.kind(),
authz.name(),
)
}
}
@ -389,19 +426,28 @@ impl svc::Param<OutboundZoneLocality> for OutboundEndpointLabels {
}
}
impl FmtLabels for OutboundEndpointLabels {
impl legacy::FmtLabels for OutboundEndpointLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(a) = self.authority.as_ref() {
let Self {
server_id,
authority,
labels,
// TODO(kate): this label is not currently emitted.
zone_locality: _,
target_addr,
} = self;
if let Some(a) = authority.as_ref() {
Authority(a).fmt_labels(f)?;
write!(f, ",")?;
}
let ta = TargetAddr(self.target_addr);
let tls = TlsConnect::from(&self.server_id);
let ta = TargetAddr(*target_addr);
let tls = TlsConnect::from(server_id);
(ta, tls).fmt_labels(f)?;
if let Some(labels) = self.labels.as_ref() {
write!(f, ",{}", labels)?;
if let Some(labels) = labels.as_ref() {
write!(f, ",{labels}")?;
}
Ok(())
@ -417,19 +463,20 @@ impl fmt::Display for Direction {
}
}
impl FmtLabels for Direction {
impl legacy::FmtLabels for Direction {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "direction=\"{}\"", self)
write!(f, "direction=\"{self}\"")
}
}
impl FmtLabels for Authority<'_> {
impl legacy::FmtLabels for Authority<'_> {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "authority=\"{}\"", self.0)
let Self(authority) = self;
write!(f, "authority=\"{authority}\"")
}
}
impl FmtLabels for Class {
impl legacy::FmtLabels for Class {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let class = |ok: bool| if ok { "success" } else { "failure" };
@ -451,8 +498,7 @@ impl FmtLabels for Class {
Class::Error(msg) => write!(
f,
"classification=\"failure\",grpc_status=\"\",error=\"{}\"",
msg
"classification=\"failure\",grpc_status=\"\",error=\"{msg}\""
),
}
}
@ -478,9 +524,15 @@ impl StackLabels {
}
}
impl FmtLabels for StackLabels {
impl legacy::FmtLabels for StackLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.direction.fmt_labels(f)?;
write!(f, ",protocol=\"{}\",name=\"{}\"", self.protocol, self.name)
let Self {
direction,
protocol,
name,
} = self;
direction.fmt_labels(f)?;
write!(f, ",protocol=\"{protocol}\",name=\"{name}\"")
}
}

View File

@ -0,0 +1,70 @@
use linkerd_metrics::prom;
use prometheus_client::encoding::{EncodeLabelSet, EncodeLabelValue, LabelValueEncoder};
use std::{
fmt::{Error, Write},
sync::{Arc, OnceLock},
};
static TLS_INFO: OnceLock<Arc<TlsInfo>> = OnceLock::new();
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, EncodeLabelSet)]
pub struct TlsInfo {
tls_suites: MetricValueList,
tls_kx_groups: MetricValueList,
tls_rand: String,
tls_key_provider: String,
tls_fips: bool,
}
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
struct MetricValueList {
values: Vec<&'static str>,
}
impl FromIterator<&'static str> for MetricValueList {
fn from_iter<T: IntoIterator<Item = &'static str>>(iter: T) -> Self {
MetricValueList {
values: iter.into_iter().collect(),
}
}
}
impl EncodeLabelValue for MetricValueList {
fn encode(&self, encoder: &mut LabelValueEncoder<'_>) -> Result<(), Error> {
for value in &self.values {
value.encode(encoder)?;
encoder.write_char(',')?;
}
Ok(())
}
}
pub fn metric() -> prom::Family<TlsInfo, prom::ConstGauge> {
let fam = prom::Family::<TlsInfo, prom::ConstGauge>::new_with_constructor(|| {
prom::ConstGauge::new(1)
});
let tls_info = TLS_INFO.get_or_init(|| {
let provider = linkerd_rustls::get_default_provider();
let tls_suites = provider
.cipher_suites
.iter()
.flat_map(|cipher_suite| cipher_suite.suite().as_str())
.collect::<MetricValueList>();
let tls_kx_groups = provider
.kx_groups
.iter()
.flat_map(|suite| suite.name().as_str())
.collect::<MetricValueList>();
Arc::new(TlsInfo {
tls_suites,
tls_kx_groups,
tls_rand: format!("{:?}", provider.secure_random),
tls_key_provider: format!("{:?}", provider.key_provider),
tls_fips: provider.fips(),
})
});
let _ = fam.get_or_create(tls_info);
fam
}

View File

@ -1,7 +1,7 @@
use crate::metrics::ServerLabel as PolicyServerLabel;
pub use crate::metrics::{Direction, OutboundEndpointLabels};
use linkerd_conditional::Conditional;
use linkerd_metrics::FmtLabels;
use linkerd_metrics::legacy::FmtLabels;
use linkerd_tls as tls;
use std::{fmt, net::SocketAddr};
@ -20,16 +20,16 @@ pub enum Key {
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ServerLabels {
direction: Direction,
tls: tls::ConditionalServerTls,
tls: tls::ConditionalServerTlsLabels,
target_addr: SocketAddr,
policy: Option<PolicyServerLabel>,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct TlsAccept<'t>(pub &'t tls::ConditionalServerTls);
pub struct TlsAccept<'t>(pub &'t tls::ConditionalServerTlsLabels);
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub(crate) struct TlsConnect<'t>(&'t tls::ConditionalClientTls);
pub(crate) struct TlsConnect<'t>(pub &'t tls::ConditionalClientTlsLabels);
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct TargetAddr(pub SocketAddr);
@ -38,7 +38,7 @@ pub struct TargetAddr(pub SocketAddr);
impl Key {
pub fn inbound_server(
tls: tls::ConditionalServerTls,
tls: tls::ConditionalServerTlsLabels,
target_addr: SocketAddr,
server: PolicyServerLabel,
) -> Self {
@ -62,7 +62,7 @@ impl FmtLabels for Key {
}
Self::InboundClient => {
const NO_TLS: tls::client::ConditionalClientTls =
const NO_TLS: tls::client::ConditionalClientTlsLabels =
Conditional::None(tls::NoClientTls::Loopback);
Direction::In.fmt_labels(f)?;
@ -75,7 +75,7 @@ impl FmtLabels for Key {
impl ServerLabels {
fn inbound(
tls: tls::ConditionalServerTls,
tls: tls::ConditionalServerTlsLabels,
target_addr: SocketAddr,
policy: PolicyServerLabel,
) -> Self {
@ -90,7 +90,7 @@ impl ServerLabels {
fn outbound(target_addr: SocketAddr) -> Self {
ServerLabels {
direction: Direction::Out,
tls: tls::ConditionalServerTls::None(tls::NoServerTls::Loopback),
tls: tls::ConditionalServerTlsLabels::None(tls::NoServerTls::Loopback),
target_addr,
policy: None,
}
@ -99,14 +99,17 @@ impl ServerLabels {
impl FmtLabels for ServerLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.direction.fmt_labels(f)?;
let Self {
direction,
tls,
target_addr,
policy,
} = self;
direction.fmt_labels(f)?;
f.write_str(",peer=\"src\",")?;
(
(TargetAddr(self.target_addr), TlsAccept(&self.tls)),
self.policy.as_ref(),
)
.fmt_labels(f)?;
((TargetAddr(*target_addr), TlsAccept(tls)), policy.as_ref()).fmt_labels(f)?;
Ok(())
}
@ -114,27 +117,28 @@ impl FmtLabels for ServerLabels {
// === impl TlsAccept ===
impl<'t> From<&'t tls::ConditionalServerTls> for TlsAccept<'t> {
fn from(c: &'t tls::ConditionalServerTls) -> Self {
impl<'t> From<&'t tls::ConditionalServerTlsLabels> for TlsAccept<'t> {
fn from(c: &'t tls::ConditionalServerTlsLabels) -> Self {
TlsAccept(c)
}
}
impl FmtLabels for TlsAccept<'_> {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
let Self(tls) = self;
match tls {
Conditional::None(tls::NoServerTls::Disabled) => {
write!(f, "tls=\"disabled\"")
}
Conditional::None(why) => {
write!(f, "tls=\"no_identity\",no_tls_reason=\"{}\"", why)
write!(f, "tls=\"no_identity\",no_tls_reason=\"{why}\"")
}
Conditional::Some(tls::ServerTls::Established { client_id, .. }) => match client_id {
Some(id) => write!(f, "tls=\"true\",client_id=\"{}\"", id),
Conditional::Some(tls::ServerTlsLabels::Established { client_id }) => match client_id {
Some(id) => write!(f, "tls=\"true\",client_id=\"{id}\""),
None => write!(f, "tls=\"true\",client_id=\"\""),
},
Conditional::Some(tls::ServerTls::Passthru { sni }) => {
write!(f, "tls=\"opaque\",sni=\"{}\"", sni)
Conditional::Some(tls::ServerTlsLabels::Passthru { sni }) => {
write!(f, "tls=\"opaque\",sni=\"{sni}\"")
}
}
}
@ -142,23 +146,25 @@ impl FmtLabels for TlsAccept<'_> {
// === impl TlsConnect ===
impl<'t> From<&'t tls::ConditionalClientTls> for TlsConnect<'t> {
fn from(s: &'t tls::ConditionalClientTls) -> Self {
impl<'t> From<&'t tls::ConditionalClientTlsLabels> for TlsConnect<'t> {
fn from(s: &'t tls::ConditionalClientTlsLabels) -> Self {
TlsConnect(s)
}
}
impl FmtLabels for TlsConnect<'_> {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
let Self(tls) = self;
match tls {
Conditional::None(tls::NoClientTls::Disabled) => {
write!(f, "tls=\"disabled\"")
}
Conditional::None(why) => {
write!(f, "tls=\"no_identity\",no_tls_reason=\"{}\"", why)
write!(f, "tls=\"no_identity\",no_tls_reason=\"{why}\"")
}
Conditional::Some(tls::ClientTls { server_id, .. }) => {
write!(f, "tls=\"true\",server_id=\"{}\"", server_id)
Conditional::Some(tls::ClientTlsLabels { server_id }) => {
write!(f, "tls=\"true\",server_id=\"{server_id}\"")
}
}
}
@ -168,12 +174,13 @@ impl FmtLabels for TlsConnect<'_> {
impl FmtLabels for TargetAddr {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self(target_addr) = self;
write!(
f,
"target_addr=\"{}\",target_ip=\"{}\",target_port=\"{}\"",
self.0,
self.0.ip(),
self.0.port()
target_addr,
target_addr.ip(),
target_addr.port()
)
}
}
@ -194,23 +201,25 @@ mod tests {
use std::sync::Arc;
let labels = ServerLabels::inbound(
tls::ConditionalServerTls::Some(tls::ServerTls::Established {
tls::ConditionalServerTlsLabels::Some(tls::ServerTlsLabels::Established {
client_id: Some("foo.id.example.com".parse().unwrap()),
negotiated_protocol: None,
}),
([192, 0, 2, 4], 40000).into(),
PolicyServerLabel(Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testserver".into(),
})),
PolicyServerLabel(
Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testserver".into(),
}),
40000,
),
);
assert_eq!(
labels.to_string(),
"direction=\"inbound\",peer=\"src\",\
target_addr=\"192.0.2.4:40000\",target_ip=\"192.0.2.4\",target_port=\"40000\",\
tls=\"true\",client_id=\"foo.id.example.com\",\
srv_group=\"policy.linkerd.io\",srv_kind=\"server\",srv_name=\"testserver\""
srv_group=\"policy.linkerd.io\",srv_kind=\"server\",srv_name=\"testserver\",srv_port=\"40000\""
);
}
}

View File

@ -1,13 +1,13 @@
[package]
name = "linkerd-app-gateway"
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
[dependencies]
http = "0.2"
http = { workspace = true }
futures = { version = "0.3", default-features = false }
linkerd-app-core = { path = "../core" }
linkerd-app-inbound = { path = "../inbound" }
@ -16,9 +16,9 @@ linkerd-proxy-client-policy = { path = "../../proxy/client-policy" }
once_cell = "1"
thiserror = "2"
tokio = { version = "1", features = ["sync"] }
tonic = { version = "0.10", default-features = false }
tower = { version = "0.4", default-features = false }
tracing = "0.1"
tonic = { workspace = true, default-features = false }
tower = { workspace = true, default-features = false }
tracing = { workspace = true }
[dev-dependencies]
linkerd-app-inbound = { path = "../inbound", features = ["test-util"] }
@ -26,6 +26,6 @@ linkerd-app-outbound = { path = "../outbound", features = ["test-util"] }
linkerd-proxy-server-policy = { path = "../../proxy/server-policy" }
tokio = { version = "1", features = ["rt", "macros"] }
tokio-test = "0.4"
tower = { version = "0.4", default-features = false, features = ["util"] }
tower-test = "0.4"
tower = { workspace = true, default-features = false, features = ["util"] }
tower-test = { workspace = true }
linkerd-app-test = { path = "../test" }

View File

@ -90,7 +90,7 @@ impl Gateway {
detect_timeout,
queue,
addr,
meta,
meta.into(),
),
None => {
tracing::debug!(

View File

@ -28,7 +28,7 @@ pub(crate) use self::gateway::NewHttpGateway;
pub struct Target<T = ()> {
addr: GatewayAddr,
routes: watch::Receiver<outbound::http::Routes>,
version: http::Version,
version: http::Variant,
parent: T,
}
@ -74,7 +74,7 @@ impl Gateway {
T: svc::Param<tls::ClientId>,
T: svc::Param<inbound::policy::AllowPolicy>,
T: svc::Param<Option<watch::Receiver<profiles::Profile>>>,
T: svc::Param<http::Version>,
T: svc::Param<http::Variant>,
T: svc::Param<http::normalize_uri::DefaultAuthority>,
T: Clone + Send + Sync + Unpin + 'static,
// Endpoint resolution.
@ -153,7 +153,7 @@ fn mk_routes(profile: &profiles::Profile) -> Option<outbound::http::Routes> {
if let Some((addr, metadata)) = profile.endpoint.clone() {
return Some(outbound::http::Routes::Endpoint(
Remote(ServerAddr(addr)),
metadata,
metadata.into(),
));
}
@ -164,7 +164,7 @@ fn mk_routes(profile: &profiles::Profile) -> Option<outbound::http::Routes> {
impl<B, T: Clone> svc::router::SelectRoute<http::Request<B>> for ByRequestVersion<T> {
type Key = Target<T>;
type Error = http::version::Unsupported;
type Error = http::UnsupportedVariant;
fn select(&self, req: &http::Request<B>) -> Result<Self::Key, Self::Error> {
let mut t = self.0.clone();
@ -192,8 +192,8 @@ impl<T> svc::Param<GatewayAddr> for Target<T> {
}
}
impl<T> svc::Param<http::Version> for Target<T> {
fn param(&self) -> http::Version {
impl<T> svc::Param<http::Variant> for Target<T> {
fn param(&self) -> http::Variant {
self.version
}
}

View File

@ -66,7 +66,7 @@ where
impl<B, S> tower::Service<http::Request<B>> for HttpGateway<S>
where
B: http::HttpBody + 'static,
B: http::Body + 'static,
S: tower::Service<http::Request<B>, Response = http::Response<http::BoxBody>>,
S::Error: Into<Error> + 'static,
S::Future: Send + 'static,

View File

@ -62,7 +62,7 @@ async fn upgraded_request_remains_relative_form() {
impl svc::Param<ServerLabel> for Target {
fn param(&self) -> ServerLabel {
ServerLabel(policy::Meta::new_default("test"))
ServerLabel(policy::Meta::new_default("test"), 4143)
}
}
@ -98,9 +98,9 @@ async fn upgraded_request_remains_relative_form() {
}
}
impl svc::Param<http::Version> for Target {
fn param(&self) -> http::Version {
http::Version::H2
impl svc::Param<http::Variant> for Target {
fn param(&self) -> http::Variant {
http::Variant::H2
}
}

View File

@ -11,7 +11,7 @@ use tokio::sync::watch;
/// Target for HTTP stacks.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Http<T> {
version: http::Version,
version: http::Variant,
parent: outbound::Discovery<T>,
}
@ -61,13 +61,13 @@ impl Gateway {
|parent: outbound::Discovery<T>| -> Result<_, GatewayDomainInvalid> {
if let Some(proto) = (*parent).param() {
let version = match proto {
SessionProtocol::Http1 => http::Version::Http1,
SessionProtocol::Http2 => http::Version::H2,
SessionProtocol::Http1 => http::Variant::Http1,
SessionProtocol::Http2 => http::Variant::H2,
};
return Ok(svc::Either::A(Http { parent, version }));
return Ok(svc::Either::Left(Http { parent, version }));
}
Ok(svc::Either::B(Opaq(parent)))
Ok(svc::Either::Right(Opaq(parent)))
},
opaq,
)
@ -154,8 +154,8 @@ impl<T> std::ops::Deref for Http<T> {
}
}
impl<T> svc::Param<http::Version> for Http<T> {
fn param(&self) -> http::Version {
impl<T> svc::Param<http::Variant> for Http<T> {
fn param(&self) -> http::Variant {
self.version
}
}

View File

@ -1,10 +1,10 @@
[package]
name = "linkerd-app-inbound"
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
description = """
Configures and runs the inbound proxy
"""
@ -13,20 +13,18 @@ Configures and runs the inbound proxy
test-util = [
"linkerd-app-test",
"linkerd-idle-cache/test-util",
"linkerd-meshtls/rustls",
"linkerd-meshtls-rustls/test-util",
"linkerd-meshtls/test-util",
]
[dependencies]
bytes = "1"
http = "0.2"
bytes = { workspace = true }
http = { workspace = true }
futures = { version = "0.3", default-features = false }
linkerd-app-core = { path = "../core" }
linkerd-app-test = { path = "../test", optional = true }
linkerd-http-access-log = { path = "../../http/access-log" }
linkerd-idle-cache = { path = "../../idle-cache" }
linkerd-meshtls = { path = "../../meshtls", optional = true }
linkerd-meshtls-rustls = { path = "../../meshtls/rustls", optional = true }
linkerd-meshtls = { path = "../../meshtls", optional = true, default-features = false }
linkerd-proxy-client-policy = { path = "../../proxy/client-policy" }
linkerd-tonic-stream = { path = "../../tonic-stream" }
linkerd-tonic-watch = { path = "../../tonic-watch" }
@ -36,28 +34,33 @@ parking_lot = "0.12"
rangemap = "1"
thiserror = "2"
tokio = { version = "1", features = ["sync"] }
tonic = { version = "0.10", default-features = false }
tower = { version = "0.4", features = ["util"] }
tracing = "0.1"
tonic = { workspace = true, default-features = false }
tower = { workspace = true, features = ["util"] }
tracing = { workspace = true }
[dependencies.linkerd-proxy-server-policy]
path = "../../proxy/server-policy"
features = ["proto"]
[target.'cfg(fuzzing)'.dependencies]
hyper = { version = "0.14", features = ["deprecated", "http1", "http2"] }
hyper = { workspace = true, features = ["http1", "http2"] }
linkerd-app-test = { path = "../test" }
arbitrary = { version = "1", features = ["derive"] }
libfuzzer-sys = { version = "0.4", features = ["arbitrary-derive"] }
linkerd-meshtls = { path = "../../meshtls", features = [
"test-util",
] }
[dev-dependencies]
hyper = { version = "0.14", features = ["deprecated", "http1", "http2"] }
http-body-util = { workspace = true }
hyper = { workspace = true, features = ["http1", "http2"] }
hyper-util = { workspace = true }
linkerd-app-test = { path = "../test" }
linkerd-http-metrics = { path = "../../http/metrics", features = ["test-util"] }
linkerd-http-box = { path = "../../http/box" }
linkerd-idle-cache = { path = "../../idle-cache", features = ["test-util"] }
linkerd-io = { path = "../../io", features = ["tokio-test"] }
linkerd-meshtls = { path = "../../meshtls", features = ["rustls"] }
linkerd-meshtls-rustls = { path = "../../meshtls/rustls", features = [
linkerd-meshtls = { path = "../../meshtls", features = [
"test-util",
] }
linkerd-proxy-server-policy = { path = "../../proxy/server-policy", features = [

View File

@ -1,10 +1,10 @@
[package]
name = "linkerd-app-inbound-fuzz"
version = "0.0.0"
version = { workspace = true }
authors = ["Automatically generated"]
publish = false
edition = "2021"
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
[package.metadata]
cargo-fuzz = true
@ -12,19 +12,18 @@ cargo-fuzz = true
[target.'cfg(fuzzing)'.dependencies]
arbitrary = { version = "1", features = ["derive"] }
hyper = { version = "0.14", features = ["deprecated", "http1", "http2"] }
http = "0.2"
http = { workspace = true }
libfuzzer-sys = { version = "0.4", features = ["arbitrary-derive"] }
linkerd-app-core = { path = "../../core" }
linkerd-app-inbound = { path = ".." }
linkerd-app-test = { path = "../../test" }
linkerd-idle-cache = { path = "../../../idle-cache", features = ["test-util"] }
linkerd-meshtls = { path = "../../../meshtls", features = ["rustls"] }
linkerd-meshtls-rustls = { path = "../../../meshtls/rustls", features = [
linkerd-meshtls = { path = "../../../meshtls", features = [
"test-util",
] }
linkerd-tracing = { path = "../../../tracing", features = ["ansi"] }
tokio = { version = "1", features = ["full"] }
tracing = "0.1"
tracing = { workspace = true }
# Prevent this from interfering with workspaces
[workspace]

View File

@ -53,12 +53,12 @@ impl<N> Inbound<N> {
move |t: T| -> Result<_, Error> {
let addr: OrigDstAddr = t.param();
if addr.port() == proxy_port {
return Ok(svc::Either::B(t));
return Ok(svc::Either::Right(t));
}
let policy = policies.get_policy(addr);
tracing::debug!(policy = ?&*policy.borrow(), "Accepted");
Ok(svc::Either::A(Accept {
Ok(svc::Either::Left(Accept {
client_addr: t.param(),
orig_dst_addr: addr,
policy,
@ -182,7 +182,11 @@ mod tests {
}
fn inbound() -> Inbound<()> {
Inbound::new(test_util::default_config(), test_util::runtime().0)
Inbound::new(
test_util::default_config(),
test_util::runtime().0,
&mut Default::default(),
)
}
fn new_panic<T>(msg: &'static str) -> svc::ArcNewTcp<T, io::DuplexStream> {

View File

@ -3,8 +3,8 @@ use crate::{
Inbound,
};
use linkerd_app_core::{
detect, identity, io,
metrics::ServerLabel,
identity, io,
metrics::{prom, ServerLabel},
proxy::http,
svc, tls,
transport::{
@ -20,6 +20,10 @@ use tracing::info;
#[cfg(test)]
mod tests;
#[derive(Clone, Debug)]
pub struct MetricsFamilies(pub HttpDetectMetrics);
pub type HttpDetectMetrics = http::DetectMetricsFamilies<ServerLabel>;
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct Forward {
client_addr: Remote<ClientAddr>,
@ -31,7 +35,7 @@ pub(crate) struct Forward {
#[derive(Clone, Debug)]
pub(crate) struct Http {
tls: Tls,
http: http::Version,
http: http::Variant,
}
#[derive(Clone, Debug)]
@ -48,9 +52,6 @@ struct Detect {
tls: Tls,
}
#[derive(Copy, Clone, Debug)]
struct ConfigureHttpDetect;
#[derive(Clone)]
struct TlsParams {
timeout: tls::server::Timeout,
@ -64,7 +65,11 @@ type TlsIo<I> = tls::server::Io<identity::ServerIo<tls::server::DetectIo<I>>, I>
impl Inbound<svc::ArcNewTcp<Http, io::BoxedIo>> {
/// Builds a stack that terminates mesh TLS and detects whether the traffic is HTTP (as hinted
/// by policy).
pub(crate) fn push_detect<T, I, F, FSvc>(self, forward: F) -> Inbound<svc::ArcNewTcp<T, I>>
pub(crate) fn push_detect<T, I, F, FSvc>(
self,
MetricsFamilies(metrics): MetricsFamilies,
forward: F,
) -> Inbound<svc::ArcNewTcp<T, I>>
where
T: svc::Param<OrigDstAddr> + svc::Param<Remote<ClientAddr>> + svc::Param<AllowPolicy>,
T: Clone + Send + 'static,
@ -75,14 +80,18 @@ impl Inbound<svc::ArcNewTcp<Http, io::BoxedIo>> {
FSvc::Error: Into<Error>,
FSvc::Future: Send,
{
self.push_detect_http(forward.clone())
self.push_detect_http(metrics, forward.clone())
.push_detect_tls(forward)
}
/// Builds a stack that handles HTTP detection once TLS detection has been performed. If the
/// connection is determined to be HTTP, the inner stack is used; otherwise the connection is
/// passed to the provided 'forward' stack.
fn push_detect_http<I, F, FSvc>(self, forward: F) -> Inbound<svc::ArcNewTcp<Tls, I>>
fn push_detect_http<I, F, FSvc>(
self,
metrics: HttpDetectMetrics,
forward: F,
) -> Inbound<svc::ArcNewTcp<Tls, I>>
where
I: io::AsyncRead + io::AsyncWrite + io::PeerAddr,
I: Debug + Send + Sync + Unpin + 'static,
@ -111,42 +120,59 @@ impl Inbound<svc::ArcNewTcp<Http, io::BoxedIo>> {
.push_switch(
|(detected, Detect { tls, .. })| -> Result<_, Infallible> {
match detected {
Ok(Some(http)) => Ok(svc::Either::A(Http { http, tls })),
Ok(None) => Ok(svc::Either::B(tls)),
http::Detection::Http(http) => {
Ok(svc::Either::Left(Http { http, tls }))
}
http::Detection::NotHttp => Ok(svc::Either::Right(tls)),
// When HTTP detection fails, forward the connection to the application as
// an opaque TCP stream.
Err(timeout) => match tls.policy.protocol() {
Protocol::Http1 { .. } => {
// If the protocol was hinted to be HTTP/1.1 but detection
// failed, we'll usually be handling HTTP/1, but we may actually
// be handling HTTP/2 via protocol upgrade. Our options are:
// handle the connection as HTTP/1, assuming it will be rare for
// a proxy to initiate TLS, etc and not send the 16B of
// connection header; or we can handle it as opaque--but there's
// no chance the server will be able to handle the H2 protocol
// upgrade. So, it seems best to assume it's HTTP/1 and let the
// proxy handle the protocol error if we're in an edge case.
info!(%timeout, "Handling connection as HTTP/1 due to policy");
Ok(svc::Either::A(Http {
http: http::Version::Http1,
tls,
}))
http::Detection::ReadTimeout(timeout) => {
match tls.policy.protocol() {
Protocol::Http1 { .. } => {
// If the protocol was hinted to be HTTP/1.1 but detection
// failed, we'll usually be handling HTTP/1, but we may actually
// be handling HTTP/2 via protocol upgrade. Our options are:
// handle the connection as HTTP/1, assuming it will be rare for
// a proxy to initiate TLS, etc and not send the 16B of
// connection header; or we can handle it as opaque--but there's
// no chance the server will be able to handle the H2 protocol
// upgrade. So, it seems best to assume it's HTTP/1 and let the
// proxy handle the protocol error if we're in an edge case.
info!(
?timeout,
"Handling connection as HTTP/1 due to policy"
);
Ok(svc::Either::Left(Http {
http: http::Variant::Http1,
tls,
}))
}
// Otherwise, the protocol hint must have
// been `Detect` or the protocol was updated
// after detection was initiated, otherwise
// we would have avoided detection below.
// Continue handling the connection as if it
// were opaque.
_ => {
info!(
?timeout,
"Handling connection as opaque due to policy"
);
Ok(svc::Either::Right(tls))
}
}
// Otherwise, the protocol hint must have been `Detect` or the
// protocol was updated after detection was initiated, otherwise we
// would have avoided detection below. Continue handling the
// connection as if it were opaque.
_ => {
info!(%timeout, "Handling connection as opaque");
Ok(svc::Either::B(tls))
}
},
}
}
},
forward.into_inner(),
)
.lift_new_with_target()
.push(detect::NewDetectService::layer(ConfigureHttpDetect))
.push(http::NewDetect::layer(
move |Detect { timeout, tls }: &Detect| http::DetectParams {
read_timeout: *timeout,
metrics: metrics.metrics(tls.policy.server_label()),
},
))
.arc_new_tcp();
http.push_on_service(svc::MapTargetLayer::new(io::BoxedIo::new))
@ -159,7 +185,7 @@ impl Inbound<svc::ArcNewTcp<Http, io::BoxedIo>> {
move |tls: Tls| -> Result<_, Infallible> {
let http = match tls.policy.protocol() {
Protocol::Detect { timeout, .. } => {
return Ok(svc::Either::B(Detect { timeout, tls }));
return Ok(svc::Either::Right(Detect { timeout, tls }));
}
// Meshed HTTP/1 services may actually be transported over HTTP/2 connections
// between proxies, so we have to do detection.
@ -167,18 +193,18 @@ impl Inbound<svc::ArcNewTcp<Http, io::BoxedIo>> {
// TODO(ver) outbound clients should hint this with ALPN so we don't
// have to detect this situation.
Protocol::Http1 { .. } if tls.status.is_some() => {
return Ok(svc::Either::B(Detect {
return Ok(svc::Either::Right(Detect {
timeout: detect_timeout,
tls,
}));
}
// Unmeshed services don't use protocol upgrading, so we can use the
// hint without further detection.
Protocol::Http1 { .. } => http::Version::Http1,
Protocol::Http2 { .. } | Protocol::Grpc { .. } => http::Version::H2,
Protocol::Http1 { .. } => http::Variant::Http1,
Protocol::Http2 { .. } | Protocol::Grpc { .. } => http::Variant::H2,
_ => unreachable!("opaque protocols must not hit the HTTP stack"),
};
Ok(svc::Either::A(Http { http, tls }))
Ok(svc::Either::Left(Http { http, tls }))
},
detect.into_inner(),
)
@ -232,10 +258,10 @@ impl<I> Inbound<svc::ArcNewTcp<Tls, TlsIo<I>>> {
// whether app TLS was employed, but we use this as a signal that we should
// not perform additional protocol detection.
if matches!(protocol, Protocol::Tls { .. }) {
return Ok(svc::Either::B(tls));
return Ok(svc::Either::Right(tls));
}
Ok(svc::Either::A(tls))
Ok(svc::Either::Left(tls))
},
forward
.clone()
@ -259,14 +285,14 @@ impl<I> Inbound<svc::ArcNewTcp<Tls, TlsIo<I>>> {
if matches!(policy.protocol(), Protocol::Opaque { .. }) {
const TLS_PORT_SKIPPED: tls::ConditionalServerTls =
tls::ConditionalServerTls::None(tls::NoServerTls::PortSkipped);
return Ok(svc::Either::B(Tls {
return Ok(svc::Either::Right(Tls {
client_addr: t.param(),
orig_dst_addr: t.param(),
status: TLS_PORT_SKIPPED,
policy,
}));
}
Ok(svc::Either::A(t))
Ok(svc::Either::Left(t))
},
forward
.push_on_service(svc::MapTargetLayer::new(io::BoxedIo::new))
@ -299,7 +325,7 @@ impl svc::Param<Remote<ServerAddr>> for Forward {
impl svc::Param<transport::labels::Key> for Forward {
fn param(&self) -> transport::labels::Key {
transport::labels::Key::inbound_server(
self.tls.clone(),
self.tls.as_ref().map(|t| t.labels()),
self.orig_dst_addr.into(),
self.permit.labels.server.clone(),
)
@ -332,18 +358,10 @@ impl svc::Param<tls::ConditionalServerTls> for Tls {
}
}
// === impl ConfigureHttpDetect ===
impl svc::ExtractParam<detect::Config<http::DetectHttp>, Detect> for ConfigureHttpDetect {
fn extract_param(&self, detect: &Detect) -> detect::Config<http::DetectHttp> {
detect::Config::from_timeout(detect.timeout)
}
}
// === impl Http ===
impl svc::Param<http::Version> for Http {
fn param(&self) -> http::Version {
impl svc::Param<http::Variant> for Http {
fn param(&self) -> http::Variant {
self.http
}
}
@ -411,7 +429,7 @@ impl svc::Param<ServerLabel> for Http {
impl svc::Param<transport::labels::Key> for Http {
fn param(&self) -> transport::labels::Key {
transport::labels::Key::inbound_server(
self.tls.status.clone(),
self.tls.status.as_ref().map(|t| t.labels()),
self.tls.orig_dst_addr.into(),
self.tls.policy.server_label(),
)
@ -442,3 +460,13 @@ impl<T> svc::InsertParam<tls::ConditionalServerTls, T> for TlsParams {
(tls, target)
}
}
// === impl MetricsFamilies ===
impl MetricsFamilies {
pub fn register(reg: &mut prom::Registry) -> Self {
Self(http::DetectMetricsFamilies::register(
reg.sub_registry_with_prefix("http"),
))
}
}

View File

@ -13,6 +13,12 @@ const HTTP1: &[u8] = b"GET / HTTP/1.1\r\nhost: example.com\r\n\r\n";
const HTTP2: &[u8] = b"PRI * HTTP/2.0\r\n";
const NOT_HTTP: &[u8] = b"foo\r\nbar\r\nblah\r\n";
const RESULTS_NOT_HTTP: &str = "results_total{result=\"not_http\",srv_group=\"policy.linkerd.io\",srv_kind=\"server\",srv_name=\"testsrv\",srv_port=\"1000\"}";
const RESULTS_HTTP1: &str = "results_total{result=\"http/1\",srv_group=\"policy.linkerd.io\",srv_kind=\"server\",srv_name=\"testsrv\",srv_port=\"1000\"}";
const RESULTS_HTTP2: &str = "results_total{result=\"http/2\",srv_group=\"policy.linkerd.io\",srv_kind=\"server\",srv_name=\"testsrv\",srv_port=\"1000\"}";
const RESULTS_READ_TIMEOUT: &str = "results_total{result=\"read_timeout\",srv_group=\"policy.linkerd.io\",srv_kind=\"server\",srv_name=\"testsrv\",srv_port=\"1000\"}";
const RESULTS_ERROR: &str = "results_total{result=\"error\",srv_group=\"policy.linkerd.io\",srv_kind=\"server\",srv_name=\"testsrv\",srv_port=\"1000\"}";
fn authzs() -> Arc<[Authorization]> {
Arc::new([Authorization {
authentication: Authentication::Unauthenticated,
@ -41,6 +47,35 @@ fn allow(protocol: Protocol) -> AllowPolicy {
allow
}
macro_rules! assert_contains_metric {
($registry:expr, $metric:expr, $value:expr) => {{
let mut buf = String::new();
prom::encoding::text::encode_registry(&mut buf, $registry).expect("encode registry failed");
let lines = buf.split_terminator('\n').collect::<Vec<_>>();
assert_eq!(
lines.iter().find(|l| l.starts_with($metric)),
Some(&&*format!("{} {}", $metric, $value)),
"metric '{}' not found in:\n{:?}",
$metric,
buf
);
}};
}
macro_rules! assert_not_contains_metric {
($registry:expr, $pattern:expr) => {{
let mut buf = String::new();
prom::encoding::text::encode_registry(&mut buf, $registry).expect("encode registry failed");
let lines = buf.split_terminator('\n').collect::<Vec<_>>();
assert!(
!lines.iter().any(|l| l.starts_with($pattern)),
"metric '{}' found in:\n{:?}",
$pattern,
buf
);
}};
}
#[tokio::test(flavor = "current_thread")]
async fn detect_tls_opaque() {
let _trace = trace::test::trace_init();
@ -77,14 +112,21 @@ async fn detect_http_non_http() {
let (ior, mut iow) = io::duplex(100);
iow.write_all(NOT_HTTP).await.unwrap();
let mut registry = prom::Registry::default();
inbound()
.with_stack(new_panic("http stack must not be used"))
.push_detect_http(new_ok())
.push_detect_http(super::HttpDetectMetrics::register(&mut registry), new_ok())
.into_inner()
.new_service(target)
.oneshot(ior)
.await
.expect("should succeed");
assert_contains_metric!(&registry, RESULTS_NOT_HTTP, 1);
assert_contains_metric!(&registry, RESULTS_HTTP1, 0);
assert_contains_metric!(&registry, RESULTS_HTTP2, 0);
assert_contains_metric!(&registry, RESULTS_READ_TIMEOUT, 0);
assert_contains_metric!(&registry, RESULTS_ERROR, 0);
}
#[tokio::test(flavor = "current_thread")]
@ -108,14 +150,24 @@ async fn detect_http() {
let (ior, mut iow) = io::duplex(100);
iow.write_all(HTTP1).await.unwrap();
let mut registry = prom::Registry::default();
inbound()
.with_stack(new_ok())
.push_detect_http(new_panic("tcp stack must not be used"))
.push_detect_http(
super::HttpDetectMetrics::register(&mut registry),
new_panic("tcp stack must not be used"),
)
.into_inner()
.new_service(target)
.oneshot(ior)
.await
.expect("should succeed");
assert_contains_metric!(&registry, RESULTS_NOT_HTTP, 0);
assert_contains_metric!(&registry, RESULTS_HTTP1, 1);
assert_contains_metric!(&registry, RESULTS_HTTP2, 0);
assert_contains_metric!(&registry, RESULTS_READ_TIMEOUT, 0);
assert_contains_metric!(&registry, RESULTS_ERROR, 0);
}
#[tokio::test(flavor = "current_thread")]
@ -134,14 +186,24 @@ async fn hinted_http1() {
let (ior, mut iow) = io::duplex(100);
iow.write_all(HTTP1).await.unwrap();
let mut registry = prom::Registry::default();
inbound()
.with_stack(new_ok())
.push_detect_http(new_panic("tcp stack must not be used"))
.push_detect_http(
super::HttpDetectMetrics::register(&mut registry),
new_panic("tcp stack must not be used"),
)
.into_inner()
.new_service(target)
.oneshot(ior)
.await
.expect("should succeed");
assert_contains_metric!(&registry, RESULTS_NOT_HTTP, 0);
assert_contains_metric!(&registry, RESULTS_HTTP1, 1);
assert_contains_metric!(&registry, RESULTS_HTTP2, 0);
assert_contains_metric!(&registry, RESULTS_READ_TIMEOUT, 0);
assert_contains_metric!(&registry, RESULTS_ERROR, 0);
}
#[tokio::test(flavor = "current_thread")]
@ -160,14 +222,24 @@ async fn hinted_http1_supports_http2() {
let (ior, mut iow) = io::duplex(100);
iow.write_all(HTTP2).await.unwrap();
let mut registry = prom::Registry::default();
inbound()
.with_stack(new_ok())
.push_detect_http(new_panic("tcp stack must not be used"))
.push_detect_http(
super::HttpDetectMetrics::register(&mut registry),
new_panic("tcp stack must not be used"),
)
.into_inner()
.new_service(target)
.oneshot(ior)
.await
.expect("should succeed");
assert_contains_metric!(&registry, RESULTS_NOT_HTTP, 0);
assert_contains_metric!(&registry, RESULTS_HTTP1, 0);
assert_contains_metric!(&registry, RESULTS_HTTP2, 1);
assert_contains_metric!(&registry, RESULTS_READ_TIMEOUT, 0);
assert_contains_metric!(&registry, RESULTS_ERROR, 0);
}
#[tokio::test(flavor = "current_thread")]
@ -185,14 +257,25 @@ async fn hinted_http2() {
let (ior, _) = io::duplex(100);
let mut registry = prom::Registry::default();
inbound()
.with_stack(new_ok())
.push_detect_http(new_panic("tcp stack must not be used"))
.push_detect_http(
super::HttpDetectMetrics::register(&mut registry),
new_panic("tcp stack must not be used"),
)
.into_inner()
.new_service(target)
.oneshot(ior)
.await
.expect("should succeed");
// No detection is performed when HTTP/2 is hinted, so no metrics are recorded.
assert_not_contains_metric!(&registry, RESULTS_NOT_HTTP);
assert_not_contains_metric!(&registry, RESULTS_HTTP1);
assert_not_contains_metric!(&registry, RESULTS_HTTP2);
assert_not_contains_metric!(&registry, RESULTS_READ_TIMEOUT);
assert_not_contains_metric!(&registry, RESULTS_ERROR);
}
fn client_id() -> tls::ClientId {
@ -210,7 +293,11 @@ fn orig_dst_addr() -> OrigDstAddr {
}
fn inbound() -> Inbound<()> {
Inbound::new(test_util::default_config(), test_util::runtime().0)
Inbound::new(
test_util::default_config(),
test_util::runtime().0,
&mut Default::default(),
)
}
fn new_panic<T, I: 'static>(msg: &'static str) -> svc::ArcNewTcp<T, I> {

View File

@ -15,6 +15,10 @@ use std::fmt::Debug;
use thiserror::Error;
use tracing::{debug_span, info_span};
mod metrics;
pub use self::metrics::MetricsFamilies;
/// Creates I/O errors when a connection cannot be forwarded because no transport
/// header was present.
#[derive(Debug, Default)]
@ -25,8 +29,8 @@ struct RefusedNoHeader;
pub struct RefusedNoIdentity(());
#[derive(Debug, Error)]
#[error("a named target must be provided on gateway connections")]
struct RefusedNoTarget;
#[error("direct connections require transport header negotiation")]
struct TransportHeaderRequired(());
#[derive(Debug, Clone)]
pub(crate) struct LocalTcp {
@ -93,7 +97,7 @@ impl<N> Inbound<N> {
self,
policies: impl policy::GetPolicy + Clone + Send + Sync + 'static,
gateway: svc::ArcNewTcp<GatewayTransportHeader, GatewayIo<I>>,
http: svc::ArcNewTcp<LocalHttp, io::PrefixedIo<TlsIo<I>>>,
http: svc::ArcNewTcp<LocalHttp, SensorIo<io::PrefixedIo<TlsIo<I>>>>,
) -> Inbound<svc::ArcNewTcp<T, I>>
where
T: Param<Remote<ClientAddr>> + Param<OrigDstAddr>,
@ -108,11 +112,12 @@ impl<N> Inbound<N> {
{
self.map_stack(|config, rt, inner| {
let detect_timeout = config.proxy.detect_protocol_timeout;
let metrics = rt.metrics.direct.clone();
let identity = rt
.identity
.server()
.with_alpn(vec![transport_header::PROTOCOL.into()])
.spawn_with_alpn(vec![transport_header::PROTOCOL.into()])
.expect("TLS credential store must be held");
inner
@ -135,7 +140,14 @@ impl<N> Inbound<N> {
// forwarding, or we may be processing an HTTP gateway connection. HTTP gateway
// connections that have a transport header must provide a target name as a part of
// the header.
.push_switch(Ok::<Local, Infallible>, http)
.push_switch(
Ok::<Local, Infallible>,
svc::stack(http)
.push(transport::metrics::NewServer::layer(
rt.metrics.proxy.transport.clone(),
))
.into_inner(),
)
.push_switch(
{
let policies = policies.clone();
@ -145,14 +157,14 @@ impl<N> Inbound<N> {
port,
name: None,
protocol,
} => Ok(svc::Either::A({
} => Ok(svc::Either::Left({
// When the transport header targets an alternate port (but does
// not identify an alternate target name), we check the new
// target's policy (rather than the inbound proxy's address).
let addr = (client.local_addr.ip(), port).into();
let policy = policies.get_policy(OrigDstAddr(addr));
match protocol {
None => svc::Either::A(LocalTcp {
None => svc::Either::Left(LocalTcp {
server_addr: Remote(ServerAddr(addr)),
client_addr: client.client_addr,
client_id: client.client_id,
@ -162,7 +174,7 @@ impl<N> Inbound<N> {
// When TransportHeader includes the protocol, but does not
// include an alternate name we go through the Inbound HTTP
// stack.
svc::Either::B(LocalHttp {
svc::Either::Right(LocalHttp {
addr: Remote(ServerAddr(addr)),
policy,
protocol,
@ -176,7 +188,7 @@ impl<N> Inbound<N> {
port,
name: Some(name),
protocol,
} => Ok(svc::Either::B({
} => Ok(svc::Either::Right({
// When the transport header provides an alternate target, the
// connection is a gateway connection. We check the _gateway
// address's_ policy (rather than the target address).
@ -204,6 +216,7 @@ impl<N> Inbound<N> {
)
.check_new_service::<(TransportHeader, ClientInfo), _>()
// Use ALPN to determine whether a transport header should be read.
.push(metrics::NewRecord::layer(metrics))
.push(svc::ArcNewService::layer())
.push(NewTransportHeaderServer::layer(detect_timeout))
.check_new_service::<ClientInfo, _>()
@ -215,7 +228,7 @@ impl<N> Inbound<N> {
if client.header_negotiated() {
Ok(client)
} else {
Err(RefusedNoTarget.into())
Err(TransportHeaderRequired(()).into())
}
})
.push(svc::ArcNewService::layer())
@ -298,9 +311,8 @@ impl Param<Remote<ServerAddr>> for AuthorizedLocalTcp {
impl Param<transport::labels::Key> for AuthorizedLocalTcp {
fn param(&self) -> transport::labels::Key {
transport::labels::Key::inbound_server(
tls::ConditionalServerTls::Some(tls::ServerTls::Established {
tls::ConditionalServerTlsLabels::Some(tls::ServerTlsLabels::Established {
client_id: Some(self.client_id.clone()),
negotiated_protocol: None,
}),
self.addr.into(),
self.permit.labels.server.clone(),
@ -331,9 +343,8 @@ impl Param<Remote<ClientAddr>> for LocalHttp {
impl Param<transport::labels::Key> for LocalHttp {
fn param(&self) -> transport::labels::Key {
transport::labels::Key::inbound_server(
tls::ConditionalServerTls::Some(tls::ServerTls::Established {
tls::ConditionalServerTlsLabels::Some(tls::ServerTlsLabels::Established {
client_id: Some(self.client.client_id.clone()),
negotiated_protocol: None,
}),
self.addr.into(),
self.policy.server_label(),
@ -347,11 +358,11 @@ impl svc::Param<policy::AllowPolicy> for LocalHttp {
}
}
impl svc::Param<http::Version> for LocalHttp {
fn param(&self) -> http::Version {
impl svc::Param<http::Variant> for LocalHttp {
fn param(&self) -> http::Variant {
match self.protocol {
SessionProtocol::Http1 => http::Version::Http1,
SessionProtocol::Http2 => http::Version::H2,
SessionProtocol::Http1 => http::Variant::Http1,
SessionProtocol::Http2 => http::Variant::H2,
}
}
}
@ -422,6 +433,14 @@ impl Param<tls::ConditionalServerTls> for GatewayTransportHeader {
}
}
impl Param<tls::ConditionalServerTlsLabels> for GatewayTransportHeader {
fn param(&self) -> tls::ConditionalServerTlsLabels {
tls::ConditionalServerTlsLabels::Some(tls::ServerTlsLabels::Established {
client_id: Some(self.client.client_id.clone()),
})
}
}
impl Param<tls::ClientId> for GatewayTransportHeader {
fn param(&self) -> tls::ClientId {
self.client.client_id.clone()

View File

@ -0,0 +1,91 @@
use super::ClientInfo;
use linkerd_app_core::{
metrics::prom::{self, EncodeLabelSetMut},
svc, tls,
transport_header::{SessionProtocol, TransportHeader},
};
#[cfg(test)]
mod tests;
#[derive(Clone, Debug)]
pub struct NewRecord<N> {
inner: N,
metrics: MetricsFamilies,
}
#[derive(Clone, Debug, Default)]
pub struct MetricsFamilies {
connections: prom::Family<Labels, prom::Counter>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
struct Labels {
header: TransportHeader,
client_id: tls::ClientId,
}
impl MetricsFamilies {
pub fn register(reg: &mut prom::Registry) -> Self {
let connections = prom::Family::default();
reg.register(
"connections",
"TCP connections with transport headers",
connections.clone(),
);
Self { connections }
}
}
impl<N> NewRecord<N> {
pub fn layer(metrics: MetricsFamilies) -> impl svc::layer::Layer<N, Service = Self> + Clone {
svc::layer::mk(move |inner| Self {
inner,
metrics: metrics.clone(),
})
}
}
impl<N> svc::NewService<(TransportHeader, ClientInfo)> for NewRecord<N>
where
N: svc::NewService<(TransportHeader, ClientInfo)>,
{
type Service = N::Service;
fn new_service(&self, (header, client): (TransportHeader, ClientInfo)) -> Self::Service {
self.metrics
.connections
.get_or_create(&Labels {
header: header.clone(),
client_id: client.client_id.clone(),
})
.inc();
self.inner.new_service((header, client))
}
}
impl prom::EncodeLabelSetMut for Labels {
fn encode_label_set(&self, enc: &mut prom::encoding::LabelSetEncoder<'_>) -> std::fmt::Result {
use prom::encoding::EncodeLabel;
(
"session_protocol",
self.header.protocol.as_ref().map(|p| match p {
SessionProtocol::Http1 => "http/1",
SessionProtocol::Http2 => "http/2",
}),
)
.encode(enc.encode_label())?;
("target_port", self.header.port).encode(enc.encode_label())?;
("target_name", self.header.name.as_deref()).encode(enc.encode_label())?;
("client_id", self.client_id.to_str()).encode(enc.encode_label())?;
Ok(())
}
}
impl prom::encoding::EncodeLabelSet for Labels {
fn encode(&self, mut enc: prom::encoding::LabelSetEncoder<'_>) -> Result<(), std::fmt::Error> {
self.encode_label_set(&mut enc)
}
}

View File

@ -0,0 +1,115 @@
use super::*;
use crate::direct::ClientInfo;
use futures::future;
use linkerd_app_core::{
io,
metrics::prom,
svc, tls,
transport::addrs::{ClientAddr, OrigDstAddr, Remote},
transport_header::{SessionProtocol, TransportHeader},
Error,
};
use std::str::FromStr;
fn new_ok<T>() -> svc::ArcNewTcp<T, io::BoxedIo> {
svc::ArcNewService::new(|_| svc::BoxService::new(svc::mk(|_| future::ok::<(), Error>(()))))
}
macro_rules! assert_counted {
($registry:expr, $proto:expr, $port:expr, $name:expr, $value:expr) => {{
let mut buf = String::new();
prom::encoding::text::encode_registry(&mut buf, $registry).expect("encode registry failed");
let metric = format!("connections_total{{session_protocol=\"{}\",target_port=\"{}\",target_name=\"{}\",client_id=\"test.client\"}}", $proto, $port, $name);
assert_eq!(
buf.split_terminator('\n')
.find(|l| l.starts_with(&*metric)),
Some(&*format!("{metric} {}", $value)),
"metric '{metric}' not found in:\n{buf}"
);
}};
}
// Added helper to setup and run the test
fn run_metric_test(header: TransportHeader) -> prom::Registry {
let mut registry = prom::Registry::default();
let families = MetricsFamilies::register(&mut registry);
let new_record = svc::layer::Layer::layer(&NewRecord::layer(families.clone()), new_ok());
// common client info
let client_id = tls::ClientId::from_str("test.client").unwrap();
let client_addr = Remote(ClientAddr(([127, 0, 0, 1], 40000).into()));
let local_addr = OrigDstAddr(([127, 0, 0, 1], 4143).into());
let client_info = ClientInfo {
client_id: client_id.clone(),
alpn: Some(tls::NegotiatedProtocol("transport.l5d.io/v1".into())),
client_addr,
local_addr,
};
let _svc = svc::NewService::new_service(&new_record, (header.clone(), client_info.clone()));
registry
}
#[test]
fn records_metrics_http1_local() {
let header = TransportHeader {
port: 8080,
name: None,
protocol: Some(SessionProtocol::Http1),
};
let registry = run_metric_test(header);
assert_counted!(&registry, "http/1", 8080, "", 1);
}
#[test]
fn records_metrics_http2_local() {
let header = TransportHeader {
port: 8081,
name: None,
protocol: Some(SessionProtocol::Http2),
};
let registry = run_metric_test(header);
assert_counted!(&registry, "http/2", 8081, "", 1);
}
#[test]
fn records_metrics_opaq_local() {
let header = TransportHeader {
port: 8082,
name: None,
protocol: None,
};
let registry = run_metric_test(header);
assert_counted!(&registry, "", 8082, "", 1);
}
#[test]
fn records_metrics_http1_gateway() {
let header = TransportHeader {
port: 8080,
name: Some("mysvc.myns.svc.cluster.local".parse().unwrap()),
protocol: Some(SessionProtocol::Http1),
};
let registry = run_metric_test(header);
assert_counted!(&registry, "http/1", 8080, "mysvc.myns.svc.cluster.local", 1);
}
#[test]
fn records_metrics_http2_gateway() {
let header = TransportHeader {
port: 8081,
name: Some("mysvc.myns.svc.cluster.local".parse().unwrap()),
protocol: Some(SessionProtocol::Http2),
};
let registry = run_metric_test(header);
assert_counted!(&registry, "http/2", 8081, "mysvc.myns.svc.cluster.local", 1);
}
#[test]
fn records_metrics_opaq_gateway() {
let header = TransportHeader {
port: 8082,
name: Some("mysvc.myns.svc.cluster.local".parse().unwrap()),
protocol: None,
};
let registry = run_metric_test(header);
assert_counted!(&registry, "", 8082, "mysvc.myns.svc.cluster.local", 1);
}

View File

@ -18,7 +18,7 @@ pub mod fuzz {
test_util::{support::connect::Connect, *},
Config, Inbound,
};
use hyper::{client::conn::Builder as ClientBuilder, Body, Request, Response};
use hyper::{Body, Request, Response};
use libfuzzer_sys::arbitrary::Arbitrary;
use linkerd_app_core::{
identity, io,
@ -41,9 +41,8 @@ pub mod fuzz {
}
pub async fn fuzz_entry_raw(requests: Vec<HttpRequestSpec>) {
let mut server = hyper::server::conn::Http::new();
server.http1_only(true);
let mut client = ClientBuilder::new();
let server = hyper::server::conn::http1::Builder::new();
let mut client = hyper::client::conn::http1::Builder::new();
let connect =
support::connect().endpoint_fn_boxed(Target::addr(), hello_fuzz_server(server));
let profiles = profile::resolver();
@ -55,7 +54,7 @@ pub mod fuzz {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_fuzz_server(cfg, rt, profiles, connect).new_service(Target::HTTP1);
let (mut client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http1(&mut client, server).await;
// Now send all of the requests
for inp in requests.iter() {
@ -74,14 +73,7 @@ pub mod fuzz {
.header(header_name, header_value)
.body(Body::default())
{
let rsp = client
.ready()
.await
.expect("HTTP client poll_ready failed")
.call(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
let rsp = client.send_request(req).await;
tracing::info!(?rsp);
if let Ok(rsp) = rsp {
let body = http_util::body_to_string(rsp.into_body()).await;
@ -93,18 +85,18 @@ pub mod fuzz {
}
}
drop(client);
// It's okay if the background task returns an error, as this would
// indicate that the proxy closed the connection --- which it will do on
// invalid inputs. We want to ensure that the proxy doesn't crash in the
// face of these inputs, and the background task will panic in this
// case.
let res = bg.await;
drop(client);
let res = bg.join_all().await;
tracing::info!(?res, "background tasks completed")
}
fn hello_fuzz_server(
http: hyper::server::conn::Http,
http: hyper::server::conn::http1::Builder,
) -> impl Fn(Remote<ServerAddr>) -> io::Result<io::BoxedIo> {
move |_endpoint| {
let (client_io, server_io) = support::io::duplex(4096);
@ -170,12 +162,12 @@ pub mod fuzz {
}
#[derive(Clone, Debug)]
struct Target(http::Version);
struct Target(http::Variant);
// === impl Target ===
impl Target {
const HTTP1: Self = Self(http::Version::Http1);
const HTTP1: Self = Self(http::Variant::Http1);
fn addr() -> SocketAddr {
([127, 0, 0, 1], 80).into()
@ -200,8 +192,8 @@ pub mod fuzz {
}
}
impl svc::Param<http::Version> for Target {
fn param(&self) -> http::Version {
impl svc::Param<http::Variant> for Target {
fn param(&self) -> http::Variant {
self.0
}
}
@ -235,6 +227,9 @@ pub mod fuzz {
kind: "server".into(),
name: "testsrv".into(),
}),
local_rate_limit: Arc::new(
linkerd_proxy_server_policy::LocalRateLimit::default(),
),
},
);
policy
@ -243,11 +238,14 @@ pub mod fuzz {
impl svc::Param<policy::ServerLabel> for Target {
fn param(&self) -> policy::ServerLabel {
policy::ServerLabel(Arc::new(policy::Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testsrv".into(),
}))
policy::ServerLabel(
Arc::new(policy::Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testsrv".into(),
}),
1000,
)
}
}

View File

@ -33,7 +33,7 @@ struct Logical {
/// The request's logical destination. Used for profile discovery.
logical: Option<NameAddr>,
addr: Remote<ServerAddr>,
http: http::Version,
http: http::Variant,
tls: tls::ConditionalServerTls,
permit: policy::HttpRoutePermit,
labels: tap::Labels,
@ -69,7 +69,7 @@ struct LogicalError {
impl<C> Inbound<C> {
pub(crate) fn push_http_router<T, P>(self, profiles: P) -> Inbound<svc::ArcNewCloneHttp<T>>
where
T: Param<http::Version>
T: Param<http::Variant>
+ Param<Remote<ServerAddr>>
+ Param<Remote<ClientAddr>>
+ Param<tls::ConditionalServerTls>
@ -83,6 +83,7 @@ impl<C> Inbound<C> {
{
self.map_stack(|config, rt, connect| {
let allow_profile = config.allow_discovery.clone();
let unsafe_authority_labels = config.unsafe_authority_labels;
let h1_params = config.proxy.connect.http1;
let h2_params = config.proxy.connect.http2.clone();
@ -105,8 +106,8 @@ impl<C> Inbound<C> {
addr: t.addr,
permit: t.permit,
params: match t.http {
http::Version::Http1 => http::client::Params::Http1(h1_params),
http::Version::H2 => http::client::Params::H2(h2_params.clone())
http::Variant::Http1 => http::client::Params::Http1(h1_params),
http::Variant::H2 => http::client::Params::H2(h2_params.clone())
},
}
})
@ -122,7 +123,9 @@ impl<C> Inbound<C> {
rt.metrics
.proxy
.http_endpoint
.to_layer::<classify::Response, _, _>(),
.to_layer_via::<classify::Response, _, _, _>(
endpoint_labels(unsafe_authority_labels),
),
)
.push_on_service(http_tracing::client(rt.span_sink.clone(), super::trace_labels()))
.push_on_service(http::BoxResponse::layer())
@ -163,14 +166,14 @@ impl<C> Inbound<C> {
|(rx, logical): (Option<profiles::Receiver>, Logical)| -> Result<_, Infallible> {
if let Some(rx) = rx {
if let Some(addr) = rx.logical_addr() {
return Ok(svc::Either::A(Profile {
return Ok(svc::Either::Left(Profile {
addr,
logical,
profiles: rx,
}));
}
}
Ok(svc::Either::B(logical))
Ok(svc::Either::Right(logical))
},
http.clone().into_inner(),
)
@ -189,7 +192,7 @@ impl<C> Inbound<C> {
// discovery (so that we skip the profile stack above).
let addr = match logical.logical.clone() {
Some(addr) => addr,
None => return Ok(svc::Either::B((None, logical))),
None => return Ok(svc::Either::Right((None, logical))),
};
if !allow_profile.matches(addr.name()) {
tracing::debug!(
@ -197,9 +200,9 @@ impl<C> Inbound<C> {
suffixes = %allow_profile,
"Skipping discovery, address not in configured DNS suffixes",
);
return Ok(svc::Either::B((None, logical)));
return Ok(svc::Either::Right((None, logical)));
}
Ok(svc::Either::A(logical))
Ok(svc::Either::Left(logical))
},
router
.check_new_service::<(Option<profiles::Receiver>, Logical), http::Request<_>>()
@ -387,13 +390,17 @@ impl Param<transport::labels::Key> for Logical {
}
}
impl Param<metrics::EndpointLabels> for Logical {
fn param(&self) -> metrics::EndpointLabels {
fn endpoint_labels(
unsafe_authority_labels: bool,
) -> impl svc::ExtractParam<metrics::EndpointLabels, Logical> + Clone {
move |t: &Logical| -> metrics::EndpointLabels {
metrics::InboundEndpointLabels {
tls: self.tls.clone(),
authority: self.logical.as_ref().map(|d| d.as_http_authority()),
target_addr: self.addr.into(),
policy: self.permit.labels.clone(),
tls: t.tls.as_ref().map(|t| t.labels()),
authority: unsafe_authority_labels
.then(|| t.logical.as_ref().map(|d| d.as_http_authority()))
.flatten(),
target_addr: t.addr.into(),
policy: t.permit.labels.clone(),
}
.into()
}

View File

@ -1,6 +1,6 @@
use super::set_identity_header::NewSetIdentityHeader;
use crate::{policy, Inbound};
pub use linkerd_app_core::proxy::http::{normalize_uri, Version};
pub use linkerd_app_core::proxy::http::{normalize_uri, Variant};
use linkerd_app_core::{
config::ProxyConfig,
errors, http_tracing, io,
@ -31,7 +31,7 @@ impl<H> Inbound<H> {
pub fn push_http_server<T, HSvc>(self) -> Inbound<svc::ArcNewCloneHttp<T>>
where
// Connection target.
T: Param<Version>
T: Param<Variant>
+ Param<normalize_uri::DefaultAuthority>
+ Param<tls::ConditionalServerTls>
+ Param<ServerLabel>
@ -95,7 +95,7 @@ impl<H> Inbound<H> {
pub fn push_http_tcp_server<T, I, HSvc>(self) -> Inbound<svc::ArcNewTcp<T, I>>
where
// Connection target.
T: Param<Version>,
T: Param<Variant>,
T: Clone + Send + Unpin + 'static,
// Server-side socket.
I: io::AsyncRead + io::AsyncWrite + io::PeerAddr + Send + Unpin + 'static,

View File

@ -6,13 +6,13 @@ use crate::{
},
Config, Inbound,
};
use hyper::{body::HttpBody, Body, Request, Response};
use hyper::{Request, Response};
use linkerd_app_core::{
classify,
errors::respond::L5D_PROXY_ERROR,
errors::header::L5D_PROXY_ERROR,
identity, io, metrics,
proxy::http,
svc::{self, http::TracingExecutor, NewService, Param},
proxy::http::{self, BoxBody},
svc::{self, http::TokioExecutor, NewService, Param},
tls,
transport::{ClientAddr, OrigDstAddr, Remote, ServerAddr},
Error, NameAddr, ProxyRuntime,
@ -33,7 +33,7 @@ fn build_server<I>(
where
I: io::AsyncRead + io::AsyncWrite + io::PeerAddr + Send + Unpin + 'static,
{
Inbound::new(cfg, rt)
Inbound::new(cfg, rt, &mut Default::default())
.with_stack(connect)
.map_stack(|cfg, _, s| {
s.push_map_target(|t| Param::<Remote<ServerAddr>>::param(&t))
@ -47,9 +47,10 @@ where
#[tokio::test(flavor = "current_thread")]
async fn unmeshed_http1_hello_world() {
let server = hyper::server::conn::http1::Builder::new();
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
let mut server = hyper::server::conn::http1::Builder::new();
server.timer(hyper_util::rt::TokioTimer::new());
let mut client = hyper::client::conn::http1::Builder::new();
let _trace = trace_init();
// Build a mock "connector" that returns the upstream "server" IO.
@ -64,15 +65,15 @@ async fn unmeshed_http1_hello_world() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::UNMESHED_HTTP1);
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http1(&mut client, server).await;
let req = Request::builder()
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.body(Body::default())
.body(BoxBody::default())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -81,6 +82,7 @@ async fn unmeshed_http1_hello_world() {
assert_eq!(body, "Hello world!");
// Wait for all of the background tasks to complete, panicking if any returned an error.
drop(client);
bg.join_all()
.await
.into_iter()
@ -91,10 +93,10 @@ async fn unmeshed_http1_hello_world() {
#[tokio::test(flavor = "current_thread")]
async fn downgrade_origin_form() {
// Reproduces https://github.com/linkerd/linkerd2/issues/5298
let server = hyper::server::conn::http1::Builder::new();
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
client.http2_only(true);
let mut server = hyper::server::conn::http1::Builder::new();
server.timer(hyper_util::rt::TokioTimer::new());
let mut client = hyper::client::conn::http2::Builder::new(TokioExecutor::new());
client.timer(hyper_util::rt::TokioTimer::new());
let _trace = trace_init();
// Build a mock "connector" that returns the upstream "server" IO.
@ -109,17 +111,45 @@ async fn downgrade_origin_form() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::UNMESHED_H2);
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = {
tracing::info!(settings = ?client, "connecting client with");
let (client_io, server_io) = io::duplex(4096);
let (client, conn) = client
.handshake(hyper_util::rt::TokioIo::new(client_io))
.await
.expect("Client must connect");
let mut bg = tokio::task::JoinSet::new();
bg.spawn(
async move {
server.oneshot(server_io).await?;
tracing::info!("proxy serve task complete");
Ok(())
}
.instrument(tracing::info_span!("proxy")),
);
bg.spawn(
async move {
conn.await?;
tracing::info!("client background complete");
Ok(())
}
.instrument(tracing::info_span!("client_bg")),
);
(client, bg)
};
let req = Request::builder()
.method(http::Method::GET)
.uri("/")
.header(http::header::HOST, "foo.svc.cluster.local")
.header("l5d-orig-proto", "HTTP/1.1")
.body(Body::default())
.body(BoxBody::empty())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -128,6 +158,7 @@ async fn downgrade_origin_form() {
assert_eq!(body, "Hello world!");
// Wait for all of the background tasks to complete, panicking if any returned an error.
drop(client);
bg.join_all()
.await
.into_iter()
@ -137,10 +168,10 @@ async fn downgrade_origin_form() {
#[tokio::test(flavor = "current_thread")]
async fn downgrade_absolute_form() {
let server = hyper::server::conn::http1::Builder::new();
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
client.http2_only(true);
let mut client = hyper::client::conn::http2::Builder::new(TokioExecutor::new());
client.timer(hyper_util::rt::TokioTimer::new());
let mut server = hyper::server::conn::http1::Builder::new();
server.timer(hyper_util::rt::TokioTimer::new());
let _trace = trace_init();
// Build a mock "connector" that returns the upstream "server" IO.
@ -155,17 +186,46 @@ async fn downgrade_absolute_form() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::UNMESHED_H2);
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = {
tracing::info!(settings = ?client, "connecting client with");
let (client_io, server_io) = io::duplex(4096);
let (client, conn) = client
.handshake(hyper_util::rt::TokioIo::new(client_io))
.await
.expect("Client must connect");
let mut bg = tokio::task::JoinSet::new();
bg.spawn(
async move {
server.oneshot(server_io).await?;
tracing::info!("proxy serve task complete");
Ok(())
}
.instrument(tracing::info_span!("proxy")),
);
bg.spawn(
async move {
conn.await?;
tracing::info!("client background complete");
Ok(())
}
.instrument(tracing::info_span!("client_bg")),
);
(client, bg)
};
let req = Request::builder()
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550/")
.header(http::header::HOST, "foo.svc.cluster.local")
.header("l5d-orig-proto", "HTTP/1.1; absolute-form")
.body(Body::default())
.body(BoxBody::empty())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -174,6 +234,7 @@ async fn downgrade_absolute_form() {
assert_eq!(body, "Hello world!");
// Wait for all of the background tasks to complete, panicking if any returned an error.
drop(client);
bg.join_all()
.await
.into_iter()
@ -190,8 +251,7 @@ async fn http1_bad_gateway_meshed_response_error_header() {
// Build a client using the connect that always errors so that responses
// are BAD_GATEWAY.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
let mut client = hyper::client::conn::http1::Builder::new();
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -199,17 +259,17 @@ async fn http1_bad_gateway_meshed_response_error_header() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::meshed_http1());
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http1(&mut client, server).await;
// Send a request and assert that it is a BAD_GATEWAY with the expected
// header message.
let req = Request::builder()
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.body(Body::default())
.body(BoxBody::default())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -218,9 +278,10 @@ async fn http1_bad_gateway_meshed_response_error_header() {
// because we don't build a real HTTP endpoint stack, which adds error
// context to this error, and the client rescue layer is below where the
// logical error context is added.
check_error_header(rsp.headers(), "server is not listening");
check_error_header(rsp.headers(), "client error (Connect)");
// Wait for all of the background tasks to complete, panicking if any returned an error.
drop(client);
bg.join_all()
.await
.into_iter()
@ -237,8 +298,7 @@ async fn http1_bad_gateway_unmeshed_response() {
// Build a client using the connect that always errors so that responses
// are BAD_GATEWAY.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
let mut client = hyper::client::conn::http1::Builder::new();
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -246,17 +306,17 @@ async fn http1_bad_gateway_unmeshed_response() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::UNMESHED_HTTP1);
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http1(&mut client, server).await;
// Send a request and assert that it is a BAD_GATEWAY with the expected
// header message.
let req = Request::builder()
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.body(Body::default())
.body(BoxBody::default())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -267,6 +327,7 @@ async fn http1_bad_gateway_unmeshed_response() {
);
// Wait for all of the background tasks to complete, panicking if any returned an error.
drop(client);
bg.join_all()
.await
.into_iter()
@ -285,8 +346,7 @@ async fn http1_connect_timeout_meshed_response_error_header() {
// Build a client using the connect that always sleeps so that responses
// are GATEWAY_TIMEOUT.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
let mut client = hyper::client::conn::http1::Builder::new();
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -294,17 +354,17 @@ async fn http1_connect_timeout_meshed_response_error_header() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::meshed_http1());
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http1(&mut client, server).await;
// Send a request and assert that it is a GATEWAY_TIMEOUT with the
// expected header message.
let req = Request::builder()
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.body(Body::default())
.body(BoxBody::default())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -314,9 +374,10 @@ async fn http1_connect_timeout_meshed_response_error_header() {
// because we don't build a real HTTP endpoint stack, which adds error
// context to this error, and the client rescue layer is below where the
// logical error context is added.
check_error_header(rsp.headers(), "connect timed out after 1s");
check_error_header(rsp.headers(), "client error (Connect)");
// Wait for all of the background tasks to complete, panicking if any returned an error.
drop(client);
bg.join_all()
.await
.into_iter()
@ -335,8 +396,7 @@ async fn http1_connect_timeout_unmeshed_response_error_header() {
// Build a client using the connect that always sleeps so that responses
// are GATEWAY_TIMEOUT.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
let mut client = hyper::client::conn::http1::Builder::new();
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -344,17 +404,17 @@ async fn http1_connect_timeout_unmeshed_response_error_header() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::UNMESHED_HTTP1);
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http1(&mut client, server).await;
// Send a request and assert that it is a GATEWAY_TIMEOUT with the
// expected header message.
let req = Request::builder()
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.body(Body::default())
.body(BoxBody::empty())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -365,6 +425,7 @@ async fn http1_connect_timeout_unmeshed_response_error_header() {
);
// Wait for all of the background tasks to complete, panicking if any returned an error.
drop(client);
bg.join_all()
.await
.into_iter()
@ -380,9 +441,8 @@ async fn h2_response_meshed_error_header() {
let connect = support::connect().endpoint_fn_boxed(Target::addr(), connect_error());
// Build a client using the connect that always errors.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
client.http2_only(true);
let mut client = hyper::client::conn::http2::Builder::new(TokioExecutor::new());
client.timer(hyper_util::rt::TokioTimer::new());
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -390,17 +450,17 @@ async fn h2_response_meshed_error_header() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::meshed_h2());
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http2(&mut client, server).await;
// Send a request and assert that it is SERVICE_UNAVAILABLE with the
// expected header message.
let req = Request::builder()
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.body(Body::default())
.body(BoxBody::empty())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -422,9 +482,8 @@ async fn h2_response_unmeshed_error_header() {
let connect = support::connect().endpoint_fn_boxed(Target::addr(), connect_error());
// Build a client using the connect that always errors.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
client.http2_only(true);
let mut client = hyper::client::conn::http2::Builder::new(TokioExecutor::new());
client.timer(hyper_util::rt::TokioTimer::new());
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -432,17 +491,17 @@ async fn h2_response_unmeshed_error_header() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::UNMESHED_H2);
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http2(&mut client, server).await;
// Send a request and assert that it is SERVICE_UNAVAILABLE with the
// expected header message.
let req = Request::builder()
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.body(Body::default())
.body(BoxBody::default())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -466,9 +525,8 @@ async fn grpc_meshed_response_error_header() {
let connect = support::connect().endpoint_fn_boxed(Target::addr(), connect_error());
// Build a client using the connect that always errors.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
client.http2_only(true);
let mut client = hyper::client::conn::http2::Builder::new(TokioExecutor::new());
client.timer(hyper_util::rt::TokioTimer::new());
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -476,7 +534,7 @@ async fn grpc_meshed_response_error_header() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::meshed_h2());
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http2(&mut client, server).await;
// Send a request and assert that it is OK with the expected header
// message.
@ -484,10 +542,10 @@ async fn grpc_meshed_response_error_header() {
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.header(http::header::CONTENT_TYPE, "application/grpc")
.body(Body::default())
.body(BoxBody::default())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -509,9 +567,8 @@ async fn grpc_unmeshed_response_error_header() {
let connect = support::connect().endpoint_fn_boxed(Target::addr(), connect_error());
// Build a client using the connect that always errors.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
client.http2_only(true);
let mut client = hyper::client::conn::http2::Builder::new(TokioExecutor::new());
client.timer(hyper_util::rt::TokioTimer::new());
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -519,7 +576,7 @@ async fn grpc_unmeshed_response_error_header() {
let cfg = default_config();
let (rt, _shutdown) = runtime();
let server = build_server(cfg, rt, profiles, connect).new_service(Target::UNMESHED_H2);
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http2(&mut client, server).await;
// Send a request and assert that it is OK with the expected header
// message.
@ -527,10 +584,10 @@ async fn grpc_unmeshed_response_error_header() {
.method(http::Method::GET)
.uri("http://foo.svc.cluster.local:5550")
.header(http::header::CONTENT_TYPE, "application/grpc")
.body(Body::default())
.body(BoxBody::default())
.unwrap();
let rsp = client
.oneshot(req)
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
@ -552,7 +609,8 @@ async fn grpc_response_class() {
// Build a mock connector serves a gRPC server that returns errors.
let connect = {
let server = hyper::server::conn::http2::Builder::new(TracingExecutor);
let mut server = hyper::server::conn::http2::Builder::new(TokioExecutor::new());
server.timer(hyper_util::rt::TokioTimer::new());
support::connect().endpoint_fn_boxed(
Target::addr(),
grpc_status_server(server, tonic::Code::Unknown),
@ -560,9 +618,8 @@ async fn grpc_response_class() {
};
// Build a client using the connect that always errors.
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut client = hyper::client::conn::Builder::new();
client.http2_only(true);
let mut client = hyper::client::conn::http2::Builder::new(TokioExecutor::new());
client.timer(hyper_util::rt::TokioTimer::new());
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
@ -575,7 +632,7 @@ async fn grpc_response_class() {
.http_endpoint
.into_report(time::Duration::from_secs(3600));
let server = build_server(cfg, rt, profiles, connect).new_service(Target::meshed_h2());
let (client, bg) = http_util::connect_and_accept(&mut client, server).await;
let (mut client, bg) = http_util::connect_and_accept_http2(&mut client, server).await;
// Send a request and assert that it is OK with the expected header
// message.
@ -583,33 +640,43 @@ async fn grpc_response_class() {
.method(http::Method::POST)
.uri("http://foo.svc.cluster.local:5550")
.header(http::header::CONTENT_TYPE, "application/grpc")
.body(Body::default())
.body(BoxBody::default())
.unwrap();
let mut rsp = client
.oneshot(req)
let rsp = client
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
assert_eq!(rsp.status(), http::StatusCode::OK);
rsp.body_mut().data().await;
let trls = rsp.body_mut().trailers().await.unwrap().unwrap();
use http_body_util::BodyExt;
let mut body = rsp.into_body();
let trls = body
.frame()
.await
.unwrap()
.unwrap()
.into_trailers()
.expect("trailers frame");
assert_eq!(trls.get("grpc-status").unwrap().to_str().unwrap(), "2");
let response_total = metrics
.get_response_total(
&metrics::EndpointLabels::Inbound(metrics::InboundEndpointLabels {
tls: Target::meshed_h2().1,
authority: Some("foo.svc.cluster.local:5550".parse().unwrap()),
tls: Target::meshed_h2().1.map(|t| t.labels()),
authority: None,
target_addr: "127.0.0.1:80".parse().unwrap(),
policy: metrics::RouteAuthzLabels {
route: metrics::RouteLabels {
server: metrics::ServerLabel(Arc::new(policy::Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testsrv".into(),
})),
server: metrics::ServerLabel(
Arc::new(policy::Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testsrv".into(),
}),
80,
),
route: policy::Meta::new_default("default"),
},
authz: Arc::new(policy::Meta::Resource {
@ -628,6 +695,104 @@ async fn grpc_response_class() {
drop(bg);
}
#[tokio::test(flavor = "current_thread")]
async fn unsafe_authority_labels_true() {
let _trace = trace_init();
let mut cfg = default_config();
cfg.unsafe_authority_labels = true;
test_unsafe_authority_labels(cfg, Some("foo.svc.cluster.local:5550".parse().unwrap())).await;
}
#[tokio::test(flavor = "current_thread")]
async fn unsafe_authority_labels_false() {
let _trace = trace_init();
let cfg = default_config();
test_unsafe_authority_labels(cfg, None).await;
}
async fn test_unsafe_authority_labels(
cfg: Config,
expected_authority: Option<http::uri::Authority>,
) {
let connect = {
let mut server = hyper::server::conn::http1::Builder::new();
server.timer(hyper_util::rt::TokioTimer::new());
support::connect().endpoint_fn_boxed(Target::addr(), hello_server(server))
};
// Build a client using the connect that always errors.
let mut client = hyper::client::conn::http1::Builder::new();
let profiles = profile::resolver();
let profile_tx =
profiles.profile_tx(NameAddr::from_str_and_port("foo.svc.cluster.local", 5550).unwrap());
profile_tx.send(profile::Profile::default()).unwrap();
let (rt, _shutdown) = runtime();
let metrics = rt
.metrics
.clone()
.http_endpoint
.into_report(time::Duration::from_secs(3600));
let server = build_server(cfg, rt, profiles, connect).new_service(Target::meshed_http1());
let (mut client, bg) = http_util::connect_and_accept_http1(&mut client, server).await;
// Send a request and assert that it is OK with the expected header
// message.
let req = Request::builder()
.method(http::Method::POST)
.uri("http://foo.svc.cluster.local:5550")
.header(http::header::CONTENT_TYPE, "text/plain")
.body(BoxBody::default())
.unwrap();
let rsp = client
.send_request(req)
.await
.expect("HTTP client request failed");
tracing::info!(?rsp);
assert_eq!(rsp.status(), http::StatusCode::OK);
use http_body_util::BodyExt;
let mut body = rsp.into_body();
while let Some(Ok(_)) = body.frame().await {}
tracing::info!("{metrics:#?}");
let response_total = metrics
.get_response_total(
&metrics::EndpointLabels::Inbound(metrics::InboundEndpointLabels {
tls: Target::meshed_http1().1.as_ref().map(|t| t.labels()),
authority: expected_authority,
target_addr: "127.0.0.1:80".parse().unwrap(),
policy: metrics::RouteAuthzLabels {
route: metrics::RouteLabels {
server: metrics::ServerLabel(
Arc::new(policy::Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testsrv".into(),
}),
80,
),
route: policy::Meta::new_default("default"),
},
authz: Arc::new(policy::Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "serverauthorization".into(),
name: "testsaz".into(),
}),
},
}),
Some(http::StatusCode::OK),
&classify::Class::Http(Ok(http::StatusCode::OK)),
)
.expect("response_total not found");
assert_eq!(response_total, 1.0);
drop(bg);
}
#[tracing::instrument]
fn hello_server(
server: hyper::server::conn::http1::Builder,
@ -637,13 +802,14 @@ fn hello_server(
let _e = span.enter();
tracing::info!("mock connecting");
let (client_io, server_io) = support::io::duplex(4096);
let hello_svc = hyper::service::service_fn(|request: Request<Body>| async move {
tracing::info!(?request);
Ok::<_, io::Error>(Response::new(Body::from("Hello world!")))
});
let hello_svc =
hyper::service::service_fn(|request: Request<hyper::body::Incoming>| async move {
tracing::info!(?request);
Ok::<_, io::Error>(Response::new(BoxBody::from_static("Hello world!")))
});
tokio::spawn(
server
.serve_connection(server_io, hello_svc)
.serve_connection(hyper_util::rt::TokioIo::new(server_io), hello_svc)
.in_current_span(),
);
Ok(io::BoxedIo::new(client_io))
@ -651,9 +817,8 @@ fn hello_server(
}
#[tracing::instrument]
#[allow(deprecated)] // linkerd/linkerd2#8733
fn grpc_status_server(
server: hyper::server::conn::http2::Builder<TracingExecutor>,
server: hyper::server::conn::http2::Builder<TokioExecutor>,
status: tonic::Code,
) -> impl Fn(Remote<ServerAddr>) -> io::Result<io::BoxedIo> {
move |endpoint| {
@ -664,26 +829,29 @@ fn grpc_status_server(
tokio::spawn(
server
.serve_connection(
server_io,
hyper::service::service_fn(move |request: Request<Body>| async move {
tracing::info!(?request);
let (mut tx, rx) = Body::channel();
tokio::spawn(async move {
let mut trls = ::http::HeaderMap::new();
trls.insert(
"grpc-status",
(status as u32).to_string().parse().unwrap(),
);
tx.send_trailers(trls).await
});
Ok::<_, io::Error>(
http::Response::builder()
.version(::http::Version::HTTP_2)
.header("content-type", "application/grpc")
.body(rx)
.unwrap(),
)
}),
hyper_util::rt::TokioIo::new(server_io),
hyper::service::service_fn(
move |request: Request<hyper::body::Incoming>| async move {
tracing::info!(?request);
let (mut tx, rx) =
http_body_util::channel::Channel::<bytes::Bytes, Error>::new(1024);
tokio::spawn(async move {
let mut trls = ::http::HeaderMap::new();
trls.insert(
"grpc-status",
(status as u32).to_string().parse().unwrap(),
);
tx.send_trailers(trls).await
});
Ok::<_, io::Error>(
http::Response::builder()
.version(::http::Version::HTTP_2)
.header("content-type", "application/grpc")
.body(rx)
.unwrap(),
)
},
),
)
.in_current_span(),
);
@ -693,12 +861,7 @@ fn grpc_status_server(
#[tracing::instrument]
fn connect_error() -> impl Fn(Remote<ServerAddr>) -> io::Result<io::BoxedIo> {
move |_| {
Err(io::Error::new(
io::ErrorKind::Other,
"server is not listening",
))
}
move |_| Err(io::Error::other("server is not listening"))
}
#[tracing::instrument]
@ -719,7 +882,7 @@ fn connect_timeout() -> Box<dyn FnMut(Remote<ServerAddr>) -> ConnectFuture + Sen
}
#[derive(Clone, Debug)]
struct Target(http::Version, tls::ConditionalServerTls);
struct Target(http::Variant, tls::ConditionalServerTls);
#[track_caller]
fn check_error_header(hdrs: &::http::HeaderMap, expected: &str) {
@ -738,17 +901,17 @@ fn check_error_header(hdrs: &::http::HeaderMap, expected: &str) {
impl Target {
const UNMESHED_HTTP1: Self = Self(
http::Version::Http1,
http::Variant::Http1,
tls::ConditionalServerTls::None(tls::NoServerTls::NoClientHello),
);
const UNMESHED_H2: Self = Self(
http::Version::H2,
http::Variant::H2,
tls::ConditionalServerTls::None(tls::NoServerTls::NoClientHello),
);
fn meshed_http1() -> Self {
Self(
http::Version::Http1,
http::Variant::Http1,
tls::ConditionalServerTls::Some(tls::ServerTls::Established {
client_id: Some(tls::ClientId(
"foosa.barns.serviceaccount.identity.linkerd.cluster.local"
@ -762,7 +925,7 @@ impl Target {
fn meshed_h2() -> Self {
Self(
http::Version::H2,
http::Variant::H2,
tls::ConditionalServerTls::Some(tls::ServerTls::Established {
client_id: Some(tls::ClientId(
"foosa.barns.serviceaccount.identity.linkerd.cluster.local"
@ -797,8 +960,8 @@ impl svc::Param<Remote<ClientAddr>> for Target {
}
}
impl svc::Param<http::Version> for Target {
fn param(&self) -> http::Version {
impl svc::Param<http::Variant> for Target {
fn param(&self) -> http::Variant {
self.0
}
}
@ -840,11 +1003,14 @@ impl svc::Param<policy::AllowPolicy> for Target {
impl svc::Param<policy::ServerLabel> for Target {
fn param(&self) -> policy::ServerLabel {
policy::ServerLabel(Arc::new(policy::Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testsrv".into(),
}))
policy::ServerLabel(
Arc::new(policy::Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "testsrv".into(),
}),
80,
)
}
}

View File

@ -20,12 +20,15 @@ pub mod test_util;
#[cfg(fuzzing)]
pub use self::http::fuzz as http_fuzz;
pub use self::{metrics::InboundMetrics, policy::DefaultPolicy};
pub use self::{
detect::MetricsFamilies as DetectMetrics, metrics::InboundMetrics, policy::DefaultPolicy,
};
use linkerd_app_core::{
config::{ConnectConfig, ProxyConfig, QueueConfig},
drain,
http_tracing::SpanSink,
identity, io,
metrics::prom,
proxy::{tap, tcp},
svc,
transport::{self, Remote, ServerAddr},
@ -52,6 +55,9 @@ pub struct Config {
/// Configures how HTTP requests are buffered *for each inbound port*.
pub http_request_queue: QueueConfig,
/// Enables unsafe authority labels.
pub unsafe_authority_labels: bool,
}
#[derive(Clone)]
@ -107,10 +113,6 @@ impl<S> Inbound<S> {
&self.runtime.identity
}
pub fn proxy_metrics(&self) -> &metrics::Proxy {
&self.runtime.metrics.proxy
}
/// A helper for gateways to instrument policy checks.
pub fn authorize_http<N>(
&self,
@ -148,9 +150,9 @@ impl<S> Inbound<S> {
}
impl Inbound<()> {
pub fn new(config: Config, runtime: ProxyRuntime) -> Self {
pub fn new(config: Config, runtime: ProxyRuntime, prom: &mut prom::Registry) -> Self {
let runtime = Runtime {
metrics: InboundMetrics::new(runtime.metrics),
metrics: InboundMetrics::new(runtime.metrics, prom),
identity: runtime.identity,
tap: runtime.tap,
span_sink: runtime.span_sink,
@ -166,7 +168,11 @@ impl Inbound<()> {
#[cfg(any(test, feature = "test-util"))]
pub fn for_test() -> (Self, drain::Signal) {
let (rt, drain) = test_util::runtime();
let this = Self::new(test_util::default_config(), rt);
let this = Self::new(
test_util::default_config(),
rt,
&mut prom::Registry::default(),
);
(this, drain)
}

View File

@ -13,7 +13,7 @@ pub(crate) mod error;
pub use linkerd_app_core::metrics::*;
/// Holds outbound proxy metrics.
/// Holds LEGACY inbound proxy metrics.
#[derive(Clone, Debug)]
pub struct InboundMetrics {
pub http_authz: authz::HttpAuthzMetrics,
@ -25,21 +25,32 @@ pub struct InboundMetrics {
/// Holds metrics that are common to both inbound and outbound proxies. These metrics are
/// reported separately
pub proxy: Proxy,
pub detect: crate::detect::MetricsFamilies,
pub direct: crate::direct::MetricsFamilies,
}
impl InboundMetrics {
pub(crate) fn new(proxy: Proxy) -> Self {
pub(crate) fn new(proxy: Proxy, reg: &mut prom::Registry) -> Self {
let detect =
crate::detect::MetricsFamilies::register(reg.sub_registry_with_prefix("tcp_detect"));
let direct = crate::direct::MetricsFamilies::register(
reg.sub_registry_with_prefix("tcp_transport_header"),
);
Self {
http_authz: authz::HttpAuthzMetrics::default(),
http_errors: error::HttpErrorMetrics::default(),
tcp_authz: authz::TcpAuthzMetrics::default(),
tcp_errors: error::TcpErrorMetrics::default(),
proxy,
detect,
direct,
}
}
}
impl FmtMetrics for InboundMetrics {
impl legacy::FmtMetrics for InboundMetrics {
fn fmt_metrics(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.http_authz.fmt_metrics(f)?;
self.http_errors.fmt_metrics(f)?;

View File

@ -1,8 +1,9 @@
use crate::policy::{AllowPolicy, HttpRoutePermit, Meta, ServerPermit};
use linkerd_app_core::{
metrics::{
metrics, Counter, FmtLabels, FmtMetrics, RouteAuthzLabels, RouteLabels, ServerAuthzLabels,
ServerLabel, TargetAddr, TlsAccept,
legacy::{Counter, FmtLabels, FmtMetrics},
metrics, RouteAuthzLabels, RouteLabels, ServerAuthzLabels, ServerLabel, TargetAddr,
TlsAccept,
},
tls,
transport::OrigDstAddr,
@ -67,7 +68,7 @@ pub struct HTTPLocalRateLimitLabels {
#[derive(Debug, Hash, PartialEq, Eq)]
struct Key<L> {
target: TargetAddr,
tls: tls::ConditionalServerTls,
tls: tls::ConditionalServerTlsLabels,
labels: L,
}
@ -80,7 +81,7 @@ type HttpLocalRateLimitKey = Key<HTTPLocalRateLimitLabels>;
// === impl HttpAuthzMetrics ===
impl HttpAuthzMetrics {
pub fn allow(&self, permit: &HttpRoutePermit, tls: tls::ConditionalServerTls) {
pub fn allow(&self, permit: &HttpRoutePermit, tls: tls::ConditionalServerTlsLabels) {
self.0
.allow
.lock()
@ -93,7 +94,7 @@ impl HttpAuthzMetrics {
&self,
labels: ServerLabel,
dst: OrigDstAddr,
tls: tls::ConditionalServerTls,
tls: tls::ConditionalServerTlsLabels,
) {
self.0
.route_not_found
@ -103,7 +104,12 @@ impl HttpAuthzMetrics {
.incr();
}
pub fn deny(&self, labels: RouteLabels, dst: OrigDstAddr, tls: tls::ConditionalServerTls) {
pub fn deny(
&self,
labels: RouteLabels,
dst: OrigDstAddr,
tls: tls::ConditionalServerTlsLabels,
) {
self.0
.deny
.lock()
@ -116,7 +122,7 @@ impl HttpAuthzMetrics {
&self,
labels: HTTPLocalRateLimitLabels,
dst: OrigDstAddr,
tls: tls::ConditionalServerTls,
tls: tls::ConditionalServerTlsLabels,
) {
self.0
.http_local_rate_limit
@ -187,7 +193,7 @@ impl FmtMetrics for HttpAuthzMetrics {
// === impl TcpAuthzMetrics ===
impl TcpAuthzMetrics {
pub fn allow(&self, permit: &ServerPermit, tls: tls::ConditionalServerTls) {
pub fn allow(&self, permit: &ServerPermit, tls: tls::ConditionalServerTlsLabels) {
self.0
.allow
.lock()
@ -196,7 +202,7 @@ impl TcpAuthzMetrics {
.incr();
}
pub fn deny(&self, policy: &AllowPolicy, tls: tls::ConditionalServerTls) {
pub fn deny(&self, policy: &AllowPolicy, tls: tls::ConditionalServerTlsLabels) {
self.0
.deny
.lock()
@ -205,7 +211,7 @@ impl TcpAuthzMetrics {
.incr();
}
pub fn terminate(&self, policy: &AllowPolicy, tls: tls::ConditionalServerTls) {
pub fn terminate(&self, policy: &AllowPolicy, tls: tls::ConditionalServerTlsLabels) {
self.0
.terminate
.lock()
@ -246,18 +252,24 @@ impl FmtMetrics for TcpAuthzMetrics {
impl FmtLabels for HTTPLocalRateLimitLabels {
fn fmt_labels(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.server.fmt_labels(f)?;
if let Some(rl) = &self.rate_limit {
let Self {
server,
rate_limit,
scope,
} = self;
server.fmt_labels(f)?;
if let Some(rl) = rate_limit {
write!(
f,
",ratelimit_group=\"{}\",ratelimit_kind=\"{}\",ratelimit_name=\"{}\",ratelimit_scope=\"{}\"",
rl.group(),
rl.kind(),
rl.name(),
self.scope,
scope,
)
} else {
write!(f, ",ratelimit_scope=\"{}\"", self.scope)
write!(f, ",ratelimit_scope=\"{scope}\"")
}
}
}
@ -265,7 +277,7 @@ impl FmtLabels for HTTPLocalRateLimitLabels {
// === impl Key ===
impl<L> Key<L> {
fn new(labels: L, dst: OrigDstAddr, tls: tls::ConditionalServerTls) -> Self {
fn new(labels: L, dst: OrigDstAddr, tls: tls::ConditionalServerTlsLabels) -> Self {
Self {
tls,
target: TargetAddr(dst.into()),
@ -276,24 +288,30 @@ impl<L> Key<L> {
impl<L: FmtLabels> FmtLabels for Key<L> {
fn fmt_labels(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self.target, (&self.labels, TlsAccept(&self.tls))).fmt_labels(f)
let Self {
target,
tls,
labels,
} = self;
(target, (labels, TlsAccept(tls))).fmt_labels(f)
}
}
impl ServerKey {
fn from_policy(policy: &AllowPolicy, tls: tls::ConditionalServerTls) -> Self {
fn from_policy(policy: &AllowPolicy, tls: tls::ConditionalServerTlsLabels) -> Self {
Self::new(policy.server_label(), policy.dst_addr(), tls)
}
}
impl RouteAuthzKey {
fn from_permit(permit: &HttpRoutePermit, tls: tls::ConditionalServerTls) -> Self {
fn from_permit(permit: &HttpRoutePermit, tls: tls::ConditionalServerTlsLabels) -> Self {
Self::new(permit.labels.clone(), permit.dst, tls)
}
}
impl ServerAuthzKey {
fn from_permit(permit: &ServerPermit, tls: tls::ConditionalServerTls) -> Self {
fn from_permit(permit: &ServerPermit, tls: tls::ConditionalServerTlsLabels) -> Self {
Self::new(permit.labels.clone(), permit.dst, tls)
}
}

View File

@ -8,7 +8,7 @@ use crate::{
};
use linkerd_app_core::{
errors::{FailFastError, LoadShedError},
metrics::FmtLabels,
metrics::legacy::FmtLabels,
tls,
};
use std::fmt;

View File

@ -1,6 +1,9 @@
use super::ErrorKind;
use linkerd_app_core::{
metrics::{metrics, Counter, FmtMetrics, ServerLabel},
metrics::{
legacy::{Counter, FmtMetrics},
metrics, ServerLabel,
},
svc::{self, stack::NewMonitor},
transport::{labels::TargetAddr, OrigDstAddr},
Error,

View File

@ -1,6 +1,9 @@
use super::ErrorKind;
use linkerd_app_core::{
metrics::{metrics, Counter, FmtMetrics},
metrics::{
legacy::{Counter, FmtMetrics},
metrics,
},
svc::{self, stack::NewMonitor},
transport::{labels::TargetAddr, OrigDstAddr},
Error,

View File

@ -133,7 +133,7 @@ impl AllowPolicy {
#[inline]
pub fn server_label(&self) -> ServerLabel {
ServerLabel(self.server.borrow().meta.clone())
ServerLabel(self.server.borrow().meta.clone(), self.dst.port())
}
pub fn ratelimit_label(&self, error: &RateLimitError) -> HTTPLocalRateLimitLabels {
@ -220,7 +220,7 @@ impl ServerPermit {
protocol: server.protocol.clone(),
labels: ServerAuthzLabels {
authz: authz.meta.clone(),
server: ServerLabel(server.meta.clone()),
server: ServerLabel(server.meta.clone(), dst.port()),
},
}
}

View File

@ -33,9 +33,8 @@ static INVALID_POLICY: once_cell::sync::OnceCell<ServerPolicy> = once_cell::sync
impl<S> Api<S>
where
S: tonic::client::GrpcService<tonic::body::BoxBody, Error = Error> + Clone,
S::ResponseBody:
http::HttpBody<Data = tonic::codegen::Bytes, Error = Error> + Default + Send + 'static,
S: tonic::client::GrpcService<tonic::body::Body, Error = Error> + Clone,
S::ResponseBody: http::Body<Data = tonic::codegen::Bytes, Error = Error> + Send + 'static,
{
pub(super) fn new(
workload: Arc<str>,
@ -58,10 +57,9 @@ where
impl<S> Service<u16> for Api<S>
where
S: tonic::client::GrpcService<tonic::body::BoxBody, Error = Error>,
S: tonic::client::GrpcService<tonic::body::Body, Error = Error>,
S: Clone + Send + Sync + 'static,
S::ResponseBody:
http::HttpBody<Data = tonic::codegen::Bytes, Error = Error> + Default + Send + 'static,
S::ResponseBody: http::Body<Data = tonic::codegen::Bytes, Error = Error> + Send + 'static,
S::Future: Send + 'static,
{
type Response =

View File

@ -40,10 +40,10 @@ impl Config {
limits: ReceiveLimits,
) -> impl GetPolicy + Clone + Send + Sync + 'static
where
C: tonic::client::GrpcService<tonic::body::BoxBody, Error = Error>,
C: tonic::client::GrpcService<tonic::body::Body, Error = Error>,
C: Clone + Unpin + Send + Sync + 'static,
C::ResponseBody: http::HttpBody<Data = tonic::codegen::Bytes, Error = Error>,
C::ResponseBody: Default + Send + 'static,
C::ResponseBody: http::Body<Data = tonic::codegen::Bytes, Error = Error>,
C::ResponseBody: Send + 'static,
C::Future: Send,
{
match self {

View File

@ -248,8 +248,11 @@ impl<T, N> HttpPolicyService<T, N> {
);
}
}
self.metrics
.deny(labels, self.connection.dst, self.connection.tls.clone());
self.metrics.deny(
labels,
self.connection.dst,
self.connection.tls.as_ref().map(|t| t.labels()),
);
return Err(HttpRouteUnauthorized(()).into());
}
};
@ -279,14 +282,19 @@ impl<T, N> HttpPolicyService<T, N> {
}
};
self.metrics.allow(&permit, self.connection.tls.clone());
self.metrics
.allow(&permit, self.connection.tls.as_ref().map(|t| t.labels()));
Ok((permit, r#match, route))
}
fn mk_route_not_found(&self) -> Error {
let labels = self.policy.server_label();
self.metrics
.route_not_found(labels, self.connection.dst, self.connection.tls.clone());
self.metrics.route_not_found(
labels,
self.connection.dst,
self.connection.tls.as_ref().map(|t| t.labels()),
);
HttpRouteNotFound(()).into()
}
@ -306,7 +314,7 @@ impl<T, N> HttpPolicyService<T, N> {
self.metrics.ratelimit(
self.policy.ratelimit_label(&err),
self.connection.dst,
self.connection.tls.clone(),
self.connection.tls.as_ref().map(|t| t.labels()),
);
err.into()
})

View File

@ -1,6 +1,7 @@
use super::*;
use crate::policy::{Authentication, Authorization, Meta, Protocol, ServerPolicy};
use linkerd_app_core::{svc::Service, Infallible};
use linkerd_http_box::BoxBody;
use linkerd_proxy_server_policy::{LocalRateLimit, RateLimitError};
macro_rules! conn {
@ -40,7 +41,7 @@ macro_rules! new_svc {
metrics: HttpAuthzMetrics::default(),
inner: |(permit, _): (HttpRoutePermit, ())| {
let f = $rsp;
svc::mk(move |req: ::http::Request<hyper::Body>| {
svc::mk(move |req: ::http::Request<BoxBody>| {
futures::future::ready((f)(permit.clone(), req))
})
},
@ -56,9 +57,9 @@ macro_rules! new_svc {
new_svc!(
$proto,
conn!(),
|permit: HttpRoutePermit, _req: ::http::Request<hyper::Body>| {
|permit: HttpRoutePermit, _req: ::http::Request<BoxBody>| {
let mut rsp = ::http::Response::builder()
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap();
rsp.extensions_mut().insert(permit.clone());
Ok::<_, Infallible>(rsp)
@ -119,11 +120,7 @@ async fn http_route() {
// Test that authorization policies allow requests:
let rsp = svc
.call(
::http::Request::builder()
.body(hyper::Body::default())
.unwrap(),
)
.call(::http::Request::builder().body(BoxBody::default()).unwrap())
.await
.expect("serves");
let permit = rsp
@ -137,7 +134,7 @@ async fn http_route() {
.call(
::http::Request::builder()
.method(::http::Method::POST)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await
@ -149,7 +146,7 @@ async fn http_route() {
.call(
::http::Request::builder()
.method(::http::Method::DELETE)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await
@ -213,11 +210,7 @@ async fn http_route() {
.expect("must send");
assert!(svc
.call(
::http::Request::builder()
.body(hyper::Body::default())
.unwrap(),
)
.call(::http::Request::builder().body(BoxBody::default()).unwrap(),)
.await
.expect_err("fails")
.is::<HttpRouteUnauthorized>());
@ -226,7 +219,7 @@ async fn http_route() {
.call(
::http::Request::builder()
.method(::http::Method::POST)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await
@ -237,7 +230,7 @@ async fn http_route() {
.call(
::http::Request::builder()
.method(::http::Method::DELETE)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await
@ -285,14 +278,14 @@ async fn http_filter_header() {
},
}],
}]));
let inner = |permit: HttpRoutePermit, req: ::http::Request<hyper::Body>| -> Result<_> {
let inner = |permit: HttpRoutePermit, req: ::http::Request<BoxBody>| -> Result<_> {
assert_eq!(req.headers().len(), 1);
assert_eq!(
req.headers().get("testkey"),
Some(&"testval".parse().unwrap())
);
let mut rsp = ::http::Response::builder()
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap();
rsp.extensions_mut().insert(permit);
Ok(rsp)
@ -300,11 +293,7 @@ async fn http_filter_header() {
let (mut svc, _tx) = new_svc!(proto, conn!(), inner);
let rsp = svc
.call(
::http::Request::builder()
.body(hyper::Body::default())
.unwrap(),
)
.call(::http::Request::builder().body(BoxBody::default()).unwrap())
.await
.expect("serves");
let permit = rsp
@ -354,16 +343,12 @@ async fn http_filter_inject_failure() {
}],
}]));
let inner = |_: HttpRoutePermit,
_: ::http::Request<hyper::Body>|
-> Result<::http::Response<hyper::Body>> { unreachable!() };
_: ::http::Request<BoxBody>|
-> Result<::http::Response<BoxBody>> { unreachable!() };
let (mut svc, _tx) = new_svc!(proto, conn!(), inner);
let err = svc
.call(
::http::Request::builder()
.body(hyper::Body::default())
.unwrap(),
)
.call(::http::Request::builder().body(BoxBody::default()).unwrap())
.await
.expect_err("fails");
assert_eq!(
@ -397,22 +382,14 @@ async fn rate_limit_allow() {
// First request should be allowed
let rsp = svc
.call(
::http::Request::builder()
.body(hyper::Body::default())
.unwrap(),
)
.call(::http::Request::builder().body(BoxBody::default()).unwrap())
.await
.expect("serves");
assert_eq!(rsp.status(), ::http::StatusCode::OK);
// Second request should be allowed as well
let rsp = svc
.call(
::http::Request::builder()
.body(hyper::Body::default())
.unwrap(),
)
.call(::http::Request::builder().body(BoxBody::default()).unwrap())
.await
.expect("serves");
assert_eq!(rsp.status(), ::http::StatusCode::OK);
@ -440,22 +417,14 @@ async fn rate_limit_deny() {
// First request should be allowed
let rsp = svc
.call(
::http::Request::builder()
.body(hyper::Body::default())
.unwrap(),
)
.call(::http::Request::builder().body(BoxBody::default()).unwrap())
.await
.expect("serves");
assert_eq!(rsp.status(), ::http::StatusCode::OK);
// Second request should be denied
let rsp = svc
.call(
::http::Request::builder()
.body(hyper::Body::default())
.unwrap(),
)
.call(::http::Request::builder().body(BoxBody::default()).unwrap())
.await
.expect_err("should deny");
let err = rsp
@ -526,7 +495,7 @@ async fn grpc_route() {
::http::Request::builder()
.uri("/foo.bar.bah/baz")
.method(::http::Method::POST)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await
@ -542,7 +511,7 @@ async fn grpc_route() {
::http::Request::builder()
.uri("/foo.bar.bah/qux")
.method(::http::Method::POST)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await
@ -554,7 +523,7 @@ async fn grpc_route() {
::http::Request::builder()
.uri("/boo.bar.bah/bah")
.method(::http::Method::POST)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await
@ -606,14 +575,14 @@ async fn grpc_filter_header() {
},
}],
}]));
let inner = |permit: HttpRoutePermit, req: ::http::Request<hyper::Body>| -> Result<_> {
let inner = |permit: HttpRoutePermit, req: ::http::Request<BoxBody>| -> Result<_> {
assert_eq!(req.headers().len(), 1);
assert_eq!(
req.headers().get("testkey"),
Some(&"testval".parse().unwrap())
);
let mut rsp = ::http::Response::builder()
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap();
rsp.extensions_mut().insert(permit);
Ok(rsp)
@ -625,7 +594,7 @@ async fn grpc_filter_header() {
::http::Request::builder()
.uri("/foo.bar.bah/baz")
.method(::http::Method::POST)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await
@ -683,8 +652,8 @@ async fn grpc_filter_inject_failure() {
}],
}]));
let inner = |_: HttpRoutePermit,
_: ::http::Request<hyper::Body>|
-> Result<::http::Response<hyper::Body>> { unreachable!() };
_: ::http::Request<BoxBody>|
-> Result<::http::Response<BoxBody>> { unreachable!() };
let (mut svc, _tx) = new_svc!(proto, conn!(), inner);
let err = svc
@ -692,7 +661,7 @@ async fn grpc_filter_inject_failure() {
::http::Request::builder()
.uri("/foo.bar.bah/baz")
.method(::http::Method::POST)
.body(hyper::Body::default())
.body(BoxBody::default())
.unwrap(),
)
.await

View File

@ -74,11 +74,10 @@ impl<S> Store<S> {
opaque_ports: RangeInclusiveSet<u16>,
) -> Self
where
S: tonic::client::GrpcService<tonic::body::BoxBody, Error = Error>,
S: tonic::client::GrpcService<tonic::body::Body, Error = Error>,
S: Clone + Send + Sync + 'static,
S::Future: Send,
S::ResponseBody:
http::HttpBody<Data = tonic::codegen::Bytes, Error = Error> + Default + Send + 'static,
S::ResponseBody: http::Body<Data = tonic::codegen::Bytes, Error = Error> + Send + 'static,
{
let opaque_default = Self::make_opaque(default.clone());
// The initial set of policies never expire from the cache.
@ -139,11 +138,10 @@ impl<S> Store<S> {
impl<S> GetPolicy for Store<S>
where
S: tonic::client::GrpcService<tonic::body::BoxBody, Error = Error>,
S: tonic::client::GrpcService<tonic::body::Body, Error = Error>,
S: Clone + Send + Sync + 'static,
S::Future: Send,
S::ResponseBody:
http::HttpBody<Data = tonic::codegen::Bytes, Error = Error> + Default + Send + 'static,
S::ResponseBody: http::Body<Data = tonic::codegen::Bytes, Error = Error> + Send + 'static,
{
fn get_policy(&self, dst: OrigDstAddr) -> AllowPolicy {
// Lookup the policy for the target port in the cache. If it doesn't

View File

@ -77,7 +77,8 @@ where
// This new services requires a ClientAddr, so it must necessarily be built for each
// connection. So we can just increment the counter here since the service can only
// be used at most once.
self.metrics.allow(&permit, tls.clone());
self.metrics
.allow(&permit, tls.as_ref().map(|t| t.labels()));
let inner = self.inner.new_service((permit, target));
TcpPolicy::Authorized(Authorized {
@ -97,7 +98,7 @@ where
?tls, %client,
"Connection denied"
);
self.metrics.deny(&policy, tls);
self.metrics.deny(&policy, tls.as_ref().map(|t| t.labels()));
TcpPolicy::Unauthorized(deny)
}
}
@ -167,7 +168,7 @@ where
%client,
"Connection terminated due to policy change",
);
metrics.terminate(&policy, tls);
metrics.terminate(&policy, tls.as_ref().map(|t| t.labels()));
return Err(denied.into());
}
}

View File

@ -43,11 +43,14 @@ async fn unauthenticated_allowed() {
kind: "serverauthorization".into(),
name: "unauth".into()
}),
server: ServerLabel(Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "test".into()
}))
server: ServerLabel(
Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "test".into()
}),
1000
)
},
}
);
@ -96,11 +99,14 @@ async fn authenticated_identity() {
kind: "serverauthorization".into(),
name: "tls-auth".into()
}),
server: ServerLabel(Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "test".into()
}))
server: ServerLabel(
Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "test".into()
}),
1000
)
}
}
);
@ -159,11 +165,14 @@ async fn authenticated_suffix() {
kind: "serverauthorization".into(),
name: "tls-auth".into()
}),
server: ServerLabel(Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "test".into()
})),
server: ServerLabel(
Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "test".into()
}),
1000
),
}
}
);
@ -219,11 +228,14 @@ async fn tls_unauthenticated() {
kind: "serverauthorization".into(),
name: "tls-unauth".into()
}),
server: ServerLabel(Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "test".into()
})),
server: ServerLabel(
Arc::new(Meta::Resource {
group: "policy.linkerd.io".into(),
kind: "server".into(),
name: "test".into()
}),
1000
),
}
}
);
@ -251,7 +263,7 @@ fn orig_dst_addr() -> OrigDstAddr {
OrigDstAddr(([192, 0, 2, 2], 1000).into())
}
impl tonic::client::GrpcService<tonic::body::BoxBody> for MockSvc {
impl tonic::client::GrpcService<tonic::body::Body> for MockSvc {
type ResponseBody = linkerd_app_core::control::RspBody;
type Error = Error;
type Future = futures::future::Pending<Result<http::Response<Self::ResponseBody>, Self::Error>>;
@ -263,7 +275,7 @@ impl tonic::client::GrpcService<tonic::body::BoxBody> for MockSvc {
unreachable!()
}
fn call(&mut self, _req: http::Request<tonic::body::BoxBody>) -> Self::Future {
fn call(&mut self, _req: http::Request<tonic::body::Body>) -> Self::Future {
unreachable!()
}
}

View File

@ -27,10 +27,10 @@ impl Inbound<()> {
limits: ReceiveLimits,
) -> impl policy::GetPolicy + Clone + Send + Sync + 'static
where
C: tonic::client::GrpcService<tonic::body::BoxBody, Error = Error>,
C: tonic::client::GrpcService<tonic::body::Body, Error = Error>,
C: Clone + Unpin + Send + Sync + 'static,
C::ResponseBody: http::HttpBody<Data = tonic::codegen::Bytes, Error = Error>,
C::ResponseBody: Default + Send + 'static,
C::ResponseBody: http::Body<Data = tonic::codegen::Bytes, Error = Error>,
C::ResponseBody: Send + 'static,
C::Future: Send,
{
self.config
@ -55,6 +55,8 @@ impl Inbound<()> {
I: Debug + Unpin + Send + Sync + 'static,
P: profiles::GetProfile<Error = Error>,
{
let detect_metrics = self.runtime.metrics.detect.clone();
// Handles connections to ports that can't be determined to be HTTP.
let forward = self
.clone()
@ -97,7 +99,7 @@ impl Inbound<()> {
// Determines how to handle an inbound connection, dispatching it to the appropriate
// stack.
http.push_http_tcp_server()
.push_detect(forward)
.push_detect(detect_metrics, forward)
.push_accept(addr.port(), policies, direct)
.into_inner()
}

View File

@ -3,9 +3,7 @@ pub use futures::prelude::*;
use linkerd_app_core::{
config,
dns::Suffix,
drain, exp_backoff,
identity::rustls,
metrics,
drain, exp_backoff, identity, metrics,
proxy::{
http::{h1, h2},
tap,
@ -89,6 +87,7 @@ pub fn default_config() -> Config {
},
discovery_idle_timeout: Duration::from_secs(20),
profile_skip_timeout: Duration::from_secs(1),
unsafe_authority_labels: false,
}
}
@ -97,7 +96,7 @@ pub fn runtime() -> (ProxyRuntime, drain::Signal) {
let (tap, _) = tap::new();
let (metrics, _) = metrics::Metrics::new(std::time::Duration::from_secs(10));
let runtime = ProxyRuntime {
identity: rustls::creds::default_for_test().1.into(),
identity: identity::creds::default_for_test().1,
metrics: metrics.proxy,
tap,
span_sink: None,

View File

@ -1,10 +1,10 @@
[package]
name = "linkerd-app-integration"
version = "0.1.0"
authors = ["Linkerd Developers <cncf-linkerd-dev@lists.cncf.io>"]
license = "Apache-2.0"
edition = "2021"
publish = false
version = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
publish = { workspace = true }
description = """
Proxy integration tests
@ -17,44 +17,56 @@ default = []
flakey = []
[dependencies]
bytes = "1"
bytes = { workspace = true }
futures = { version = "0.3", default-features = false, features = ["executor"] }
h2 = "0.3"
http = "0.2"
http-body = "0.4"
hyper = { version = "0.14", features = [
"deprecated",
"http1",
"http2",
"stream",
"client",
"server",
] }
h2 = { workspace = true }
http = { workspace = true }
http-body = { workspace = true }
http-body-util = { workspace = true }
hyper-util = { workspace = true, features = ["service"] }
ipnet = "2"
linkerd-app = { path = "..", features = ["allow-loopback"] }
linkerd-app-core = { path = "../core" }
linkerd-metrics = { path = "../../metrics", features = ["test_util"] }
linkerd2-proxy-api = { workspace = true, features = [
"destination",
"arbitrary",
] }
linkerd-app-test = { path = "../test" }
linkerd-meshtls = { path = "../../meshtls", features = ["test-util"] }
linkerd-metrics = { path = "../../metrics", features = ["test_util"] }
linkerd-rustls = { path = "../../rustls" }
linkerd-tracing = { path = "../../tracing" }
maplit = "1"
parking_lot = "0.12"
regex = "1"
socket2 = "0.5"
rustls-pemfile = "2.2"
socket2 = "0.6"
tokio = { version = "1", features = ["io-util", "net", "rt", "macros"] }
tokio-rustls = { workspace = true }
tokio-stream = { version = "0.1", features = ["sync"] }
tokio-rustls = "0.24"
rustls-pemfile = "1.0"
tower = { version = "0.4", default-features = false }
tonic = { version = "0.10", features = ["transport"], default-features = false }
tracing = "0.1"
tracing-subscriber = { version = "0.3", default-features = false, features = [
tonic = { workspace = true, features = ["transport", "router"], default-features = false }
tower = { workspace = true, default-features = false }
tracing = { workspace = true }
[dependencies.hyper]
workspace = true
features = [
"client",
"http1",
"http2",
"server",
]
[dependencies.linkerd2-proxy-api]
workspace = true
features = [
"arbitrary",
"destination",
]
[dependencies.tracing-subscriber]
version = "0.3"
default-features = false
features = [
"fmt",
"std",
] }
]
[dev-dependencies]
flate2 = { version = "1", default-features = false, features = [
@ -62,8 +74,5 @@ flate2 = { version = "1", default-features = false, features = [
] }
# Log streaming isn't enabled by default globally, but we want to test it.
linkerd-app-admin = { path = "../admin", features = ["log-streaming"] }
# No code from this crate is actually used; only necessary to enable the Rustls
# implementation.
linkerd-meshtls = { path = "../../meshtls", features = ["rustls"] }
linkerd-tracing = { path = "../../tracing", features = ["ansi"] }
serde_json = "1"

View File

@ -1,26 +1,28 @@
use super::*;
use linkerd_app_core::proxy::http::TracingExecutor;
use http::{Request, Response};
use linkerd_app_core::{proxy::http::TokioExecutor, svc::http::BoxBody};
use parking_lot::Mutex;
use std::io;
use tokio::net::TcpStream;
use tokio::task::JoinHandle;
use tokio::{net::TcpStream, task::JoinHandle};
use tokio_rustls::rustls::{self, ClientConfig};
use tracing::info_span;
type ClientError = hyper::Error;
type Request = http::Request<hyper::Body>;
type Response = http::Response<hyper::Body>;
type Sender = mpsc::UnboundedSender<(Request, oneshot::Sender<Result<Response, ClientError>>)>;
type ClientError = hyper_util::client::legacy::Error;
type Sender = mpsc::UnboundedSender<(
Request<BoxBody>,
oneshot::Sender<Result<Response<hyper::body::Incoming>, ClientError>>,
)>;
#[derive(Clone)]
pub struct TlsConfig {
client_config: Arc<ClientConfig>,
name: rustls::ServerName,
name: rustls::pki_types::ServerName<'static>,
}
impl TlsConfig {
pub fn new(client_config: Arc<ClientConfig>, name: &str) -> Self {
let name = rustls::ServerName::try_from(name).expect("name must be a valid DNS name");
pub fn new(client_config: Arc<ClientConfig>, name: &'static str) -> Self {
let name =
rustls::pki_types::ServerName::try_from(name).expect("name must be a valid DNS name");
TlsConfig {
client_config,
name,
@ -74,9 +76,6 @@ pub fn http2_tls<T: Into<String>>(addr: SocketAddr, auth: T, tls: TlsConfig) ->
Client::new(addr, auth.into(), Run::Http2, Some(tls))
}
pub fn tcp(addr: SocketAddr) -> tcp::TcpClient {
tcp::client(addr)
}
pub struct Client {
addr: SocketAddr,
run: Run,
@ -132,11 +131,19 @@ impl Client {
pub fn request(
&self,
builder: http::request::Builder,
) -> impl Future<Output = Result<Response, ClientError>> + Send + Sync + 'static {
self.send_req(builder.body(Bytes::new().into()).unwrap())
) -> impl Future<Output = Result<Response<hyper::body::Incoming>, ClientError>> + Send + 'static
{
let req = builder.body(BoxBody::empty()).unwrap();
self.send_req(req)
}
pub async fn request_body(&self, req: Request) -> Response {
pub async fn request_body<B>(&self, req: Request<B>) -> Response<hyper::body::Incoming>
where
B: Body + Send + 'static,
B::Data: Send + 'static,
B::Error: Into<Error>,
{
let req = req.map(BoxBody::new);
self.send_req(req).await.expect("response")
}
@ -152,11 +159,16 @@ impl Client {
}
}
#[tracing::instrument(skip(self))]
pub(crate) fn send_req(
#[tracing::instrument(skip(self, req))]
pub(crate) fn send_req<B>(
&self,
mut req: Request,
) -> impl Future<Output = Result<Response, ClientError>> + Send + Sync + 'static {
mut req: Request<B>,
) -> impl Future<Output = Result<Response<hyper::body::Incoming>, ClientError>> + Send + 'static
where
B: Body + Send + 'static,
B::Data: Send + 'static,
B::Error: Into<Error>,
{
if req.uri().scheme().is_none() {
if self.tls.is_some() {
*req.uri_mut() = format!("https://{}{}", self.authority, req.uri().path())
@ -170,7 +182,8 @@ impl Client {
}
tracing::debug!(headers = ?req.headers(), "request");
let (tx, rx) = oneshot::channel();
let _ = self.tx.send((req.map(Into::into), tx));
let req = req.map(BoxBody::new);
let _ = self.tx.send((req, tx));
async { rx.await.expect("request cancelled") }.in_current_span()
}
@ -220,13 +233,17 @@ enum Run {
Http2,
}
pub type Running = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;
fn run(
addr: SocketAddr,
version: Run,
tls: Option<TlsConfig>,
) -> (Sender, JoinHandle<()>, Running) {
let (tx, rx) =
mpsc::unbounded_channel::<(Request, oneshot::Sender<Result<Response, ClientError>>)>();
let (tx, rx) = mpsc::unbounded_channel::<(
Request<BoxBody>,
oneshot::Sender<Result<Response<hyper::body::Incoming>, ClientError>>,
)>();
let test_name = thread_name();
let absolute_uris = if let Run::Http1 { absolute_uris } = version {
@ -235,7 +252,12 @@ fn run(
false
};
let (running_tx, running) = running();
let (running_tx, running) = {
let (tx, rx) = oneshot::channel();
let rx = Box::pin(rx.map(|_| ()));
(tx, rx)
};
let conn = Conn {
addr,
absolute_uris,
@ -250,10 +272,9 @@ fn run(
let span = info_span!("test client", peer_addr = %addr, ?version, test = %test_name);
let work = async move {
let client = hyper::Client::builder()
let client = hyper_util::client::legacy::Client::builder(TokioExecutor::new())
.http2_only(http2_only)
.executor(TracingExecutor)
.build::<Conn, hyper::Body>(conn);
.build::<Conn, BoxBody>(conn);
tracing::trace!("client task started");
let mut rx = rx;
let (drain_tx, drain) = drain::channel();
@ -263,7 +284,6 @@ fn run(
// instance would remain un-dropped.
async move {
while let Some((req, cb)) = rx.recv().await {
let req = req.map(hyper::Body::from);
tracing::trace!(?req);
let req = client.request(req);
tokio::spawn(
@ -295,9 +315,11 @@ struct Conn {
}
impl tower::Service<hyper::Uri> for Conn {
type Response = RunningIo;
type Response = hyper_util::rt::TokioIo<RunningIo>;
type Error = io::Error;
type Future = Pin<Box<dyn Future<Output = io::Result<RunningIo>> + Send + 'static>>;
type Future = Pin<
Box<dyn Future<Output = io::Result<hyper_util::rt::TokioIo<RunningIo>>> + Send + 'static>,
>;
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
@ -327,19 +349,19 @@ impl tower::Service<hyper::Uri> for Conn {
} else {
Box::pin(io) as Pin<Box<dyn Io + Send + 'static>>
};
Ok(RunningIo {
Ok(hyper_util::rt::TokioIo::new(RunningIo {
io,
abs_form,
_running: Some(running),
})
}))
})
}
}
impl hyper::client::connect::Connection for RunningIo {
fn connected(&self) -> hyper::client::connect::Connected {
impl hyper_util::client::legacy::connect::Connection for RunningIo {
fn connected(&self) -> hyper_util::client::legacy::connect::Connected {
// Setting `proxy` to true will configure Hyper to use absolute-form
// URIs on this connection.
hyper::client::connect::Connected::new().proxy(self.abs_form)
hyper_util::client::legacy::connect::Connected::new().proxy(self.abs_form)
}
}

View File

@ -2,7 +2,7 @@ use super::*;
pub use linkerd2_proxy_api::destination as pb;
use linkerd2_proxy_api::net;
use linkerd_app_core::proxy::http::TracingExecutor;
use linkerd_app_core::proxy::http::TokioExecutor;
use parking_lot::Mutex;
use std::collections::VecDeque;
use std::net::IpAddr;
@ -262,10 +262,7 @@ impl pb::destination_server::Destination for Controller {
}
tracing::warn!(?dst, ?updates, "request does not match");
let msg = format!(
"expected get call for {:?} but got get call for {:?}",
dst, req
);
let msg = format!("expected get call for {dst:?} but got get call for {req:?}");
calls.push_front(Dst::Call(dst, updates));
return Err(grpc::Status::new(grpc::Code::Unavailable, msg));
}
@ -343,7 +340,7 @@ pub(crate) async fn run<T, B>(
delay: Option<Pin<Box<dyn Future<Output = ()> + Send>>>,
) -> Listening
where
T: tower::Service<http::Request<hyper::body::Body>, Response = http::Response<B>>,
T: tower::Service<http::Request<hyper::body::Incoming>, Response = http::Response<B>>,
T: Clone + Send + 'static,
T::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
T::Future: Send,
@ -372,13 +369,16 @@ where
let _ = listening_tx.send(());
}
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut http = hyper::server::conn::Http::new().with_executor(TracingExecutor);
http.http2_only(true);
let mut http = hyper::server::conn::http2::Builder::new(TokioExecutor::new());
loop {
let (sock, addr) = listener.accept().await?;
let span = tracing::debug_span!("conn", %addr).or_current();
let serve = http.serve_connection(sock, svc.clone());
let serve = http
.timer(hyper_util::rt::TokioTimer::new())
.serve_connection(
hyper_util::rt::TokioIo::new(sock),
hyper_util::service::TowerToHyperService::new(svc.clone()),
);
let f = async move {
serve.await.map_err(|error| {
tracing::error!(

View File

@ -8,7 +8,8 @@ use std::{
};
use linkerd2_proxy_api::identity as pb;
use tokio_rustls::rustls;
use linkerd_rustls::get_default_provider;
use tokio_rustls::rustls::{self, server::WebPkiClientVerifier};
use tonic as grpc;
pub struct Identity {
@ -34,10 +35,6 @@ type Certify = Box<
> + Send,
>;
static TLS_VERSIONS: &[&rustls::SupportedProtocolVersion] = &[&rustls::version::TLS13];
static TLS_SUPPORTED_CIPHERSUITES: &[rustls::SupportedCipherSuite] =
&[rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256];
struct Certificates {
pub leaf: Vec<u8>,
pub intermediates: Vec<Vec<u8>>,
@ -50,11 +47,17 @@ impl Certificates {
{
let f = fs::File::open(p)?;
let mut r = io::BufReader::new(f);
let mut certs = rustls_pemfile::certs(&mut r)
.map_err(|_| io::Error::new(io::ErrorKind::Other, "rustls error reading certs"))?;
let mut certs = certs.drain(..);
let leaf = certs.next().expect("no leaf cert in pemfile");
let intermediates = certs.collect();
let mut certs = rustls_pemfile::certs(&mut r);
let leaf = certs
.next()
.expect("no leaf cert in pemfile")
.map_err(|_| io::Error::other("rustls error reading certs"))?
.as_ref()
.to_vec();
let intermediates = certs
.map(|cert| cert.map(|cert| cert.as_ref().to_vec()))
.collect::<Result<Vec<_>, _>>()
.map_err(|_| io::Error::other("rustls error reading certs"))?;
Ok(Certificates {
leaf,
@ -62,11 +65,14 @@ impl Certificates {
})
}
pub fn chain(&self) -> Vec<rustls::Certificate> {
pub fn chain(&self) -> Vec<rustls::pki_types::CertificateDer<'static>> {
let mut chain = Vec::with_capacity(self.intermediates.len() + 1);
chain.push(self.leaf.clone());
chain.extend(self.intermediates.clone());
chain.into_iter().map(rustls::Certificate).collect()
chain
.into_iter()
.map(rustls::pki_types::CertificateDer::from)
.collect()
}
pub fn response(&self) -> pb::CertifyResponse {
@ -79,43 +85,46 @@ impl Certificates {
}
impl Identity {
fn load_key<P>(p: P) -> rustls::PrivateKey
fn load_key<P>(p: P) -> rustls::pki_types::PrivateKeyDer<'static>
where
P: AsRef<Path>,
{
let p8 = fs::read(&p).expect("read key");
rustls::PrivateKey(p8)
rustls::pki_types::PrivateKeyDer::try_from(p8).expect("decode key")
}
fn configs(
trust_anchors: &str,
certs: &Certificates,
key: rustls::PrivateKey,
key: rustls::pki_types::PrivateKeyDer<'static>,
) -> (Arc<rustls::ClientConfig>, Arc<rustls::ServerConfig>) {
use std::io::Cursor;
let mut roots = rustls::RootCertStore::empty();
let trust_anchors =
rustls_pemfile::certs(&mut Cursor::new(trust_anchors)).expect("error parsing pemfile");
let (added, skipped) = roots.add_parsable_certificates(&trust_anchors[..]);
let trust_anchors = rustls_pemfile::certs(&mut Cursor::new(trust_anchors))
.collect::<Result<Vec<_>, _>>()
.expect("error parsing pemfile");
let (added, skipped) = roots.add_parsable_certificates(trust_anchors);
assert_ne!(added, 0, "trust anchors must include at least one cert");
assert_eq!(skipped, 0, "no certs in pemfile should be invalid");
let client_config = rustls::ClientConfig::builder()
.with_cipher_suites(TLS_SUPPORTED_CIPHERSUITES)
.with_safe_default_kx_groups()
.with_protocol_versions(TLS_VERSIONS)
let provider = get_default_provider();
let client_config = rustls::ClientConfig::builder_with_provider(provider.clone())
.with_safe_default_protocol_versions()
.expect("client config must be valid")
.with_root_certificates(roots.clone())
.with_no_client_auth();
let server_config = rustls::ServerConfig::builder()
.with_cipher_suites(TLS_SUPPORTED_CIPHERSUITES)
.with_safe_default_kx_groups()
.with_protocol_versions(TLS_VERSIONS)
let client_cert_verifier =
WebPkiClientVerifier::builder_with_provider(Arc::new(roots), provider.clone())
.allow_unauthenticated()
.build()
.expect("server verifier must be valid");
let server_config = rustls::ServerConfig::builder_with_provider(provider)
.with_safe_default_protocol_versions()
.expect("server config must be valid")
.with_client_cert_verifier(Arc::new(
rustls::server::AllowAnyAnonymousOrAuthenticatedClient::new(roots),
))
.with_client_cert_verifier(client_cert_verifier)
.with_single_cert(certs.chain(), key)
.unwrap();
@ -204,7 +213,7 @@ impl Controller {
let f = f.take().expect("called twice?");
let fut = f(req)
.map_ok(grpc::Response::new)
.map_err(|e| grpc::Status::new(grpc::Code::Internal, format!("{}", e)));
.map_err(|e| grpc::Status::new(grpc::Code::Internal, format!("{e}")));
Box::pin(fut)
});
self.expect_calls.lock().push_back(func);

View File

@ -3,6 +3,7 @@
#![warn(rust_2018_idioms, clippy::disallowed_methods, clippy::disallowed_types)]
#![forbid(unsafe_code)]
#![recursion_limit = "256"]
#![allow(clippy::result_large_err)]
mod test_env;
@ -26,9 +27,9 @@ pub use bytes::{Buf, BufMut, Bytes};
pub use futures::stream::{Stream, StreamExt};
pub use futures::{future, FutureExt, TryFuture, TryFutureExt};
pub use http::{HeaderMap, Request, Response, StatusCode};
pub use http_body::Body as HttpBody;
pub use http_body::Body;
pub use linkerd_app as app;
pub use linkerd_app_core::{drain, Addr};
pub use linkerd_app_core::{drain, Addr, Error};
pub use linkerd_app_test::*;
pub use linkerd_tracing::test::*;
use socket2::Socket;
@ -50,8 +51,6 @@ pub use tower::Service;
pub const ENV_TEST_PATIENCE_MS: &str = "RUST_TEST_PATIENCE_MS";
pub const DEFAULT_TEST_PATIENCE: Duration = Duration::from_millis(15);
pub type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
/// Retry an assertion up to a specified number of times, waiting
/// `RUST_TEST_PATIENCE_MS` between retries.
///
@ -219,15 +218,6 @@ impl Shutdown {
pub type ShutdownRx = Pin<Box<dyn Future<Output = ()> + Send>>;
/// A channel used to signal when a Client's related connection is running or closed.
pub fn running() -> (oneshot::Sender<()>, Running) {
let (tx, rx) = oneshot::channel();
let rx = Box::pin(rx.map(|_| ()));
(tx, rx)
}
pub type Running = Pin<Box<dyn Future<Output = ()> + Send + Sync + 'static>>;
pub fn s(bytes: &[u8]) -> &str {
::std::str::from_utf8(bytes).unwrap()
}
@ -258,7 +248,7 @@ impl fmt::Display for HumanDuration {
let secs = self.0.as_secs();
let subsec_ms = self.0.subsec_nanos() as f64 / 1_000_000f64;
if secs == 0 {
write!(fmt, "{}ms", subsec_ms)
write!(fmt, "{subsec_ms}ms")
} else {
write!(fmt, "{}s", secs as f64 + subsec_ms)
}
@ -267,7 +257,7 @@ impl fmt::Display for HumanDuration {
pub async fn cancelable<E: Send + 'static>(
drain: drain::Watch,
f: impl Future<Output = Result<(), E>> + Send + 'static,
f: impl Future<Output = Result<(), E>>,
) -> Result<(), E> {
tokio::select! {
res = f => res,

View File

@ -2,6 +2,7 @@ use super::*;
pub use api::{inbound, outbound};
use api::{inbound::inbound_server_policies_server, outbound::outbound_policies_server};
use futures::stream;
use http_body_util::combinators::UnsyncBoxBody;
use linkerd2_proxy_api as api;
use parking_lot::Mutex;
use std::collections::VecDeque;
@ -34,6 +35,9 @@ pub struct InboundSender(Tx<inbound::Server>);
#[derive(Debug, Clone)]
pub struct OutboundSender(Tx<outbound::OutboundPolicy>);
#[derive(Clone)]
struct RoutesSvc(grpc::service::Routes);
type Tx<T> = mpsc::UnboundedSender<Result<T, grpc::Status>>;
type Rx<T> = UnboundedReceiverStream<Result<T, grpc::Status>>;
type WatchStream<T> = Pin<Box<dyn Stream<Item = Result<T, grpc::Status>> + Send + Sync + 'static>>;
@ -298,7 +302,7 @@ impl Controller {
}
pub async fn run(self) -> controller::Listening {
let svc = grpc::transport::Server::builder()
let routes = grpc::service::Routes::default()
.add_service(
inbound_server_policies_server::InboundServerPoliciesServer::new(Server(Arc::new(
self.inbound,
@ -306,9 +310,9 @@ impl Controller {
)
.add_service(outbound_policies_server::OutboundPoliciesServer::new(
Server(Arc::new(self.outbound)),
))
.into_service();
controller::run(svc, "support policy controller", None).await
));
controller::run(RoutesSvc(routes), "support policy controller", None).await
}
}
@ -509,6 +513,35 @@ impl<Req, Rsp> Inner<Req, Rsp> {
}
}
// === impl RoutesSvc ===
impl Service<Request<hyper::body::Incoming>> for RoutesSvc {
type Response =
<grpc::service::Routes as Service<Request<UnsyncBoxBody<Bytes, grpc::Status>>>>::Response;
type Error =
<grpc::service::Routes as Service<Request<UnsyncBoxBody<Bytes, grpc::Status>>>>::Error;
type Future =
<grpc::service::Routes as Service<Request<UnsyncBoxBody<Bytes, grpc::Status>>>>::Future;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
let Self(routes) = self;
<grpc::service::Routes as Service<Request<UnsyncBoxBody<Bytes, grpc::Status>>>>::poll_ready(
routes, cx,
)
}
fn call(&mut self, req: Request<hyper::body::Incoming>) -> Self::Future {
use http_body_util::{combinators::UnsyncBoxBody, BodyExt};
let Self(routes) = self;
let req = req.map(|body| {
UnsyncBoxBody::new(body.map_err(|err| grpc::Status::from_error(Box::new(err))))
});
routes.call(req)
}
}
fn grpc_no_results() -> grpc::Status {
grpc::Status::new(
grpc::Code::NotFound,

View File

@ -108,7 +108,7 @@ impl fmt::Debug for MockOrigDst {
match self {
Self::Addr(addr) => f
.debug_tuple("MockOrigDst::Addr")
.field(&format_args!("{}", addr))
.field(&format_args!("{addr}"))
.finish(),
Self::Direct => f.debug_tuple("MockOrigDst::Direct").finish(),
Self::None => f.debug_tuple("MockOrigDst::None").finish(),
@ -416,9 +416,9 @@ async fn run(proxy: Proxy, mut env: TestEnv, random_ports: bool) -> Listening {
use std::fmt::Write;
let mut ports = inbound_default_ports.iter();
if let Some(port) = ports.next() {
let mut var = format!("{}", port);
let mut var = format!("{port}");
for port in ports {
write!(&mut var, ",{}", port).expect("writing to String should never fail");
write!(&mut var, ",{port}").expect("writing to String should never fail");
}
info!("{}={:?}", app::env::ENV_INBOUND_PORTS, var);
env.put(app::env::ENV_INBOUND_PORTS, var);

View File

@ -1,5 +1,7 @@
use super::app_core::svc::http::TracingExecutor;
use super::app_core::svc::http::TokioExecutor;
use super::*;
use http::{Request, Response};
use linkerd_app_core::svc::http::BoxBody;
use std::{
io,
sync::atomic::{AtomicUsize, Ordering},
@ -12,23 +14,35 @@ pub fn new() -> Server {
}
pub fn http1() -> Server {
Server::http1()
Server {
routes: Default::default(),
version: Run::Http1,
tls: None,
}
}
pub fn http1_tls(tls: Arc<ServerConfig>) -> Server {
Server::http1_tls(tls)
Server {
routes: Default::default(),
version: Run::Http1,
tls: Some(tls),
}
}
pub fn http2() -> Server {
Server::http2()
Server {
routes: Default::default(),
version: Run::Http2,
tls: None,
}
}
pub fn http2_tls(tls: Arc<ServerConfig>) -> Server {
Server::http2_tls(tls)
}
pub fn tcp() -> tcp::TcpServer {
tcp::server()
Server {
routes: Default::default(),
version: Run::Http2,
tls: Some(tls),
}
}
pub struct Server {
@ -45,9 +59,8 @@ pub struct Listening {
pub(super) http_version: Option<Run>,
}
type Request = http::Request<hyper::Body>;
type Response = http::Response<hyper::Body>;
type RspFuture = Pin<Box<dyn Future<Output = Result<Response, BoxError>> + Send + Sync + 'static>>;
type RspFuture<B = BoxBody> =
Pin<Box<dyn Future<Output = Result<Response<B>, Error>> + Send + 'static>>;
impl Listening {
pub fn connections(&self) -> usize {
@ -92,29 +105,6 @@ impl Listening {
}
impl Server {
fn new(run: Run, tls: Option<Arc<ServerConfig>>) -> Self {
Server {
routes: HashMap::new(),
version: run,
tls,
}
}
fn http1() -> Self {
Server::new(Run::Http1, None)
}
fn http1_tls(tls: Arc<ServerConfig>) -> Self {
Server::new(Run::Http1, Some(tls))
}
fn http2() -> Self {
Server::new(Run::Http2, None)
}
fn http2_tls(tls: Arc<ServerConfig>) -> Self {
Server::new(Run::Http2, Some(tls))
}
/// Return a string body as a 200 OK response, with the string as
/// the response body.
pub fn route(mut self, path: &str, resp: &str) -> Self {
@ -126,11 +116,11 @@ impl Server {
/// to send back.
pub fn route_fn<F>(self, path: &str, cb: F) -> Self
where
F: Fn(Request) -> Response + Send + Sync + 'static,
F: Fn(Request<BoxBody>) -> Response<BoxBody> + Send + Sync + 'static,
{
self.route_async(path, move |req| {
let res = cb(req);
async move { Ok::<_, BoxError>(res) }
async move { Ok::<_, Error>(res) }
})
}
@ -138,9 +128,9 @@ impl Server {
/// a response to send back.
pub fn route_async<F, U>(mut self, path: &str, cb: F) -> Self
where
F: Fn(Request) -> U + Send + Sync + 'static,
U: TryFuture<Ok = Response> + Send + Sync + 'static,
U::Error: Into<BoxError> + Send + 'static,
F: Fn(Request<BoxBody>) -> U + Send + Sync + 'static,
U: TryFuture<Ok = Response<BoxBody>> + Send + 'static,
U::Error: Into<Error> + Send + 'static,
{
let func = move |req| Box::pin(cb(req).map_err(Into::into)) as RspFuture;
self.routes.insert(path.into(), Route(Box::new(func)));
@ -148,16 +138,17 @@ impl Server {
}
pub fn route_with_latency(self, path: &str, resp: &str, latency: Duration) -> Self {
let resp = Bytes::from(resp.to_string());
let body = resp.to_owned();
self.route_async(path, move |_| {
let resp = resp.clone();
let body = body.clone();
async move {
tokio::time::sleep(latency).await;
Ok::<_, BoxError>(
Ok::<_, Error>(
http::Response::builder()
.status(200)
.body(hyper::Body::from(resp.clone()))
.unwrap(),
.status(StatusCode::OK)
.body(http_body_util::Full::new(Bytes::from(body.clone())))
.unwrap()
.map(BoxBody::new),
)
}
})
@ -193,13 +184,7 @@ impl Server {
drain.clone(),
async move {
tracing::info!("support server running");
let mut new_svc = NewSvc(Arc::new(self.routes));
#[allow(deprecated)] // linkerd/linkerd2#8733
let mut http = hyper::server::conn::Http::new().with_executor(TracingExecutor);
match self.version {
Run::Http1 => http.http1_only(true),
Run::Http2 => http.http2_only(true),
};
let svc = Svc(Arc::new(self.routes));
if let Some(delay) = delay {
let _ = listening_tx.take().unwrap().send(());
delay.await;
@ -218,27 +203,41 @@ impl Server {
let sock = accept_connection(sock, tls_config.clone())
.instrument(span.clone())
.await?;
let http = http.clone();
let srv_conn_count = srv_conn_count.clone();
let svc = new_svc.call(());
let svc = svc.clone();
let f = async move {
tracing::trace!("serving...");
let svc = svc.await;
tracing::trace!("service acquired");
srv_conn_count.fetch_add(1, Ordering::Release);
let svc = svc.map_err(|e| {
tracing::error!("support/server new_service error: {}", e)
})?;
let result = http
.serve_connection(sock, svc)
.await
.map_err(|e| tracing::error!("support/server error: {}", e));
use hyper_util::{rt::TokioIo, service::TowerToHyperService};
let (sock, svc) = (TokioIo::new(sock), TowerToHyperService::new(svc));
let result = match self.version {
Run::Http1 => hyper::server::conn::http1::Builder::new()
.timer(hyper_util::rt::TokioTimer::new())
.serve_connection(sock, svc)
.await
.map_err(|e| tracing::error!("support/server error: {}", e)),
Run::Http2 => {
hyper::server::conn::http2::Builder::new(TokioExecutor::new())
.timer(hyper_util::rt::TokioTimer::new())
.serve_connection(sock, svc)
.await
.map_err(|e| tracing::error!("support/server error: {}", e))
}
};
tracing::trace!(?result, "serve done");
result
};
tokio::spawn(
cancelable(drain.clone(), f).instrument(span.clone().or_current()),
);
// let fut = Box::pin(cancelable(drain.clone(), f).instrument(span.clone().or_current()))
let drain = drain.clone();
tokio::spawn(async move {
tokio::select! {
res = f => res,
_ = drain.signaled() => {
tracing::debug!("canceled!");
Ok(())
}
}
});
}
}
.instrument(
@ -267,17 +266,19 @@ pub(super) enum Run {
Http2,
}
struct Route(Box<dyn Fn(Request) -> RspFuture + Send + Sync>);
struct Route(Box<dyn Fn(Request<BoxBody>) -> RspFuture + Send + Sync>);
impl Route {
fn string(body: &str) -> Route {
let body = Bytes::from(body.to_string());
let body = http_body_util::Full::new(Bytes::from(body.to_string()));
Route(Box::new(move |_| {
let body = body.clone();
Box::pin(future::ok(
http::Response::builder()
.status(200)
.body(hyper::Body::from(body.clone()))
.unwrap(),
.status(StatusCode::OK)
.body(body)
.unwrap()
.map(BoxBody::new),
))
}))
}
@ -289,58 +290,53 @@ impl std::fmt::Debug for Route {
}
}
type BoxError = Box<dyn std::error::Error + Send + Sync>;
#[derive(Debug)]
#[derive(Clone, Debug)]
struct Svc(Arc<HashMap<String, Route>>);
impl Svc {
fn route(&mut self, req: Request) -> RspFuture {
fn route<B>(
&mut self,
req: Request<B>,
) -> impl Future<Output = Result<Response<BoxBody>, crate::app_core::Error>> + Send
where
B: Body + Send + Sync + 'static,
B::Data: Send + 'static,
B::Error: std::error::Error + Send + Sync + 'static,
{
match self.0.get(req.uri().path()) {
Some(Route(ref func)) => {
tracing::trace!(path = %req.uri().path(), "found route for path");
func(req)
func(req.map(BoxBody::new))
}
None => {
tracing::warn!("server 404: {:?}", req.uri().path());
let res = http::Response::builder()
.status(404)
.body(Default::default())
.unwrap();
Box::pin(async move { Ok(res) })
Box::pin(futures::future::ok(
http::Response::builder()
.status(StatusCode::NOT_FOUND)
.body(BoxBody::empty())
.unwrap(),
))
}
}
}
}
impl tower::Service<Request> for Svc {
type Response = Response;
type Error = BoxError;
impl<B> tower::Service<Request<B>> for Svc
where
B: Body + Send + Sync + 'static,
B::Data: Send,
B::Error: std::error::Error + Send + Sync,
{
type Response = Response<BoxBody>;
type Error = Error;
type Future = RspFuture;
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Request) -> Self::Future {
self.route(req)
}
}
#[derive(Debug)]
struct NewSvc(Arc<HashMap<String, Route>>);
impl Service<()> for NewSvc {
type Response = Svc;
type Error = ::std::io::Error;
type Future = future::Ready<Result<Svc, Self::Error>>;
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _: ()) -> Self::Future {
future::ok(Svc(Arc::clone(&self.0)))
fn call(&mut self, req: Request<B>) -> Self::Future {
Box::pin(self.route(req))
}
}
@ -358,7 +354,6 @@ async fn accept_connection(
_running: None,
})
}
None => Ok(RunningIo {
io: Box::pin(io),
abs_form: false,

View File

@ -2,6 +2,7 @@ use super::*;
use futures::stream;
use http_body::Body;
use linkerd2_proxy_api::tap as pb;
use linkerd_app_core::svc::http::BoxBody;
pub fn client(addr: SocketAddr) -> Client {
let api = pb::tap_client::TapClient::new(SyncSvc(client::http2(addr, "localhost")));
@ -106,7 +107,6 @@ pub trait TapEventExt {
//fn id(&self) -> (u32, u64);
fn event(&self) -> &pb::tap_event::http::Event;
fn request_init_method(&self) -> String;
fn request_init_authority(&self) -> &str;
fn request_init_path(&self) -> &str;
@ -134,41 +134,31 @@ impl TapEventExt for pb::TapEvent {
}
}
fn request_init_method(&self) -> String {
match self.event() {
pb::tap_event::http::Event::RequestInit(_ev) => {
//TODO: ugh
unimplemented!("method");
}
e => panic!("not RequestInit event: {:?}", e),
}
}
fn request_init_authority(&self) -> &str {
match self.event() {
pb::tap_event::http::Event::RequestInit(ev) => &ev.authority,
e => panic!("not RequestInit event: {:?}", e),
e => panic!("not RequestInit event: {e:?}"),
}
}
fn request_init_path(&self) -> &str {
match self.event() {
pb::tap_event::http::Event::RequestInit(ev) => &ev.path,
e => panic!("not RequestInit event: {:?}", e),
e => panic!("not RequestInit event: {e:?}"),
}
}
fn response_init_status(&self) -> u16 {
match self.event() {
pb::tap_event::http::Event::ResponseInit(ev) => ev.http_status as u16,
e => panic!("not ResponseInit event: {:?}", e),
e => panic!("not ResponseInit event: {e:?}"),
}
}
fn response_end_bytes(&self) -> u64 {
match self.event() {
pb::tap_event::http::Event::ResponseEnd(ev) => ev.response_bytes,
e => panic!("not ResponseEnd event: {:?}", e),
e => panic!("not ResponseEnd event: {e:?}"),
}
}
@ -180,7 +170,7 @@ impl TapEventExt for pb::TapEvent {
}) => code,
_ => panic!("not Eos GrpcStatusCode: {:?}", ev.eos),
},
ev => panic!("not ResponseEnd event: {:?}", ev),
ev => panic!("not ResponseEnd event: {ev:?}"),
}
}
}
@ -188,15 +178,14 @@ impl TapEventExt for pb::TapEvent {
struct SyncSvc(client::Client);
type ResponseFuture =
Pin<Box<dyn Future<Output = Result<http::Response<hyper::Body>, String>> + Send>>;
Pin<Box<dyn Future<Output = Result<http::Response<hyper::body::Incoming>, String>> + Send>>;
impl<B> tower::Service<http::Request<B>> for SyncSvc
where
B: Body + Send + 'static,
B::Data: Send + 'static,
B::Error: Send + 'static,
B: Body,
B::Error: std::fmt::Debug,
{
type Response = http::Response<hyper::Body>;
type Response = http::Response<hyper::body::Incoming>;
type Error = String;
type Future = ResponseFuture;
@ -205,20 +194,31 @@ where
}
fn call(&mut self, req: http::Request<B>) -> Self::Future {
// this is okay to do because the body should always be complete, we
// just can't prove it.
let req = futures::executor::block_on(async move {
let (parts, body) = req.into_parts();
let body = match body.collect().await.map(http_body::Collected::to_bytes) {
Ok(body) => body,
Err(_) => unreachable!("body should not fail"),
};
http::Request::from_parts(parts, body)
});
Box::pin(
self.0
.send_req(req.map(Into::into))
.map_err(|err| err.to_string()),
)
use http_body_util::Full;
let Self(client) = self;
let req = req.map(Self::collect_body).map(Full::new).map(BoxBody::new);
let fut = client.send_req(req).map_err(|err| err.to_string());
Box::pin(fut)
}
}
impl SyncSvc {
/// Collects the given [`Body`], returning a [`Bytes`].
///
/// NB: This blocks the current thread until the provided body has been collected. This is
/// an acceptable practice in test code for the sake of simplicitly, because we will always
/// provide [`SyncSvc`] with bodies that are complete.
fn collect_body<B>(body: B) -> Bytes
where
B: Body,
B::Error: std::fmt::Debug,
{
futures::executor::block_on(async move {
use http_body_util::BodyExt;
body.collect()
.await
.expect("body should not fail")
.to_bytes()
})
}
}

View File

@ -1,10 +1,11 @@
use super::*;
use std::collections::VecDeque;
use std::io;
use std::net::TcpListener as StdTcpListener;
use std::sync::atomic::{AtomicUsize, Ordering};
use tokio::net::TcpStream;
use tokio::task::JoinHandle;
use std::{
collections::VecDeque,
io,
net::TcpListener as StdTcpListener,
sync::atomic::{AtomicUsize, Ordering},
};
use tokio::{net::TcpStream, task::JoinHandle};
type TcpConnSender = mpsc::UnboundedSender<(
Option<Vec<u8>>,
@ -148,10 +149,6 @@ impl TcpServer {
}
impl TcpConn {
pub fn target_addr(&self) -> SocketAddr {
self.addr
}
pub async fn read(&self) -> Vec<u8> {
self.try_read()
.await

View File

@ -381,7 +381,7 @@ mod cross_version {
}
fn default_dst_name(port: u16) -> String {
format!("{}:{}", HOST, port)
format!("{HOST}:{port}")
}
fn send_default_dst(
@ -484,7 +484,7 @@ mod http2 {
let body = {
let body = res.into_body();
let body = http_body::Body::collect(body)
let body = http_body_util::BodyExt::collect(body)
.await
.unwrap()
.to_bytes()

View File

@ -24,7 +24,7 @@ async fn nonblocking_identity_detection() {
let msg1 = "custom tcp hello\n";
let msg2 = "custom tcp bye";
let srv = server::tcp()
let srv = crate::tcp::server()
.accept(move |read| {
assert_eq!(read, msg1.as_bytes());
msg2
@ -33,7 +33,7 @@ async fn nonblocking_identity_detection() {
.await;
let proxy = proxy.inbound(srv).run_with_test_env(env).await;
let client = client::tcp(proxy.inbound);
let client = crate::tcp::client(proxy.inbound);
// Create an idle connection and then an active connection. Ensure that
// protocol detection on the idle connection does not block communication on

View File

@ -1,5 +1,6 @@
use crate::*;
use linkerd2_proxy_api::destination as pb;
use linkerd_app_core::svc::http::BoxBody;
use std::sync::atomic::{AtomicUsize, Ordering};
struct Service {
@ -14,11 +15,17 @@ impl Service {
let counter = response_counter.clone();
let svc = server::http1()
.route_fn("/load-profile", |_| {
Response::builder().status(201).body("".into()).unwrap()
Response::builder()
.status(201)
.body(BoxBody::empty())
.unwrap()
})
.route_fn("/", move |_req| {
counter.fetch_add(1, Ordering::SeqCst);
Response::builder().status(200).body(name.into()).unwrap()
Response::builder()
.status(200)
.body(BoxBody::from_static(name))
.unwrap()
})
.run()
.await;
@ -56,7 +63,7 @@ async fn wait_for_profile_stage(client: &client::Client, metrics: &client::Clien
for _ in 0i32..10 {
assert_eq!(client.get("/load-profile").await, "");
let m = metrics.get("/metrics").await;
let stage_metric = format!("rt_load_profile=\"{}\"", stage);
let stage_metric = format!("rt_load_profile=\"{stage}\"");
if m.contains(stage_metric.as_str()) {
break;
}

View File

@ -1,3 +1,5 @@
use linkerd_app_core::svc::http::BoxBody;
use crate::*;
use std::sync::atomic::{AtomicUsize, Ordering};
@ -71,7 +73,10 @@ impl TestBuilder {
// This route is just called by the test setup, to trigger the proxy
// to start fetching the ServiceProfile.
.route_fn("/load-profile", |_| {
Response::builder().status(201).body("".into()).unwrap()
Response::builder()
.status(201)
.body(BoxBody::empty())
.unwrap()
});
if self.default_routes {
@ -83,12 +88,12 @@ impl TestBuilder {
let port = srv.addr.port();
let ctrl = controller::new();
let dst_tx = ctrl.destination_tx(format!("{}:{}", host, port));
let dst_tx = ctrl.destination_tx(format!("{host}:{port}"));
dst_tx.send_addr(srv.addr);
let ctrl = controller::new();
let dst_tx = ctrl.destination_tx(format!("{}:{}", host, port));
let dst_tx = ctrl.destination_tx(format!("{host}:{port}"));
dst_tx.send_addr(srv.addr);
let profile_tx = ctrl.profile_tx(srv.addr.to_string());
@ -121,7 +126,7 @@ impl TestBuilder {
::std::thread::sleep(Duration::from_secs(1));
Response::builder()
.status(200)
.body("slept".into())
.body(BoxBody::from_static("slept"))
.unwrap()
})
.route_async("/0.5", move |req| {
@ -129,17 +134,20 @@ impl TestBuilder {
async move {
// Read the entire body before responding, so that the
// client doesn't fail when writing it out.
let body = http_body::Body::collect(req.into_body())
let body = http_body_util::BodyExt::collect(req.into_body())
.await
.map(http_body::Collected::to_bytes);
.map(http_body_util::Collected::to_bytes);
let bytes = body.as_ref().map(Bytes::len);
tracing::debug!(?bytes, "recieved body");
Ok::<_, Error>(if fail {
Response::builder().status(533).body("nope".into()).unwrap()
Response::builder()
.status(533)
.body(BoxBody::from_static("nope"))
.unwrap()
} else {
Response::builder()
.status(200)
.body("retried".into())
.body(BoxBody::from_static("retried"))
.unwrap()
})
}
@ -147,11 +155,14 @@ impl TestBuilder {
.route_fn("/0.5/sleep", move |_req| {
::std::thread::sleep(Duration::from_secs(1));
if counter2.fetch_add(1, Ordering::Relaxed) % 2 == 0 {
Response::builder().status(533).body("nope".into()).unwrap()
Response::builder()
.status(533)
.body(BoxBody::from_static("nope"))
.unwrap()
} else {
Response::builder()
.status(200)
.body("retried".into())
.body(BoxBody::from_static("retried"))
.unwrap()
}
})
@ -159,12 +170,15 @@ impl TestBuilder {
if counter3.fetch_add(1, Ordering::Relaxed) % 2 == 0 {
Response::builder()
.status(533)
.body(vec![b'x'; 1024 * 100].into())
.body(BoxBody::new(http_body_util::Full::new(Bytes::from(vec![
b'x';
1024 * 100
]))))
.unwrap()
} else {
Response::builder()
.status(200)
.body("retried".into())
.body(BoxBody::from_static("retried"))
.unwrap()
}
})
@ -185,6 +199,8 @@ impl TestBuilder {
}
mod cross_version {
use std::convert::Infallible;
use super::*;
pub(super) async fn retry_if_profile_allows(version: server::Server) {
@ -248,7 +264,7 @@ mod cross_version {
let req = client
.request_builder("/0.5")
.method(http::Method::POST)
.body("req has a body".into())
.body(BoxBody::from_static("req has a body"))
.unwrap();
let res = client.request_body(req).await;
assert_eq!(res.status(), 200);
@ -269,7 +285,7 @@ mod cross_version {
let req = client
.request_builder("/0.5")
.method(http::Method::PUT)
.body("req has a body".into())
.body(BoxBody::from_static("req has a body"))
.unwrap();
let res = client.request_body(req).await;
assert_eq!(res.status(), 200);
@ -287,13 +303,14 @@ mod cross_version {
.await;
let client = test.client;
let (mut tx, body) = hyper::body::Body::channel();
let (mut tx, body) = http_body_util::channel::Channel::<Bytes, Infallible>::new(1024);
let req = client
.request_builder("/0.5")
.method("POST")
.body(body)
.unwrap();
let res = tokio::spawn(async move { client.request_body(req).await });
let fut = client.send_req(req);
let res = tokio::spawn(fut);
tx.send_data(Bytes::from_static(b"hello"))
.await
.expect("the whole body should be read");
@ -301,7 +318,7 @@ mod cross_version {
.await
.expect("the whole body should be read");
drop(tx);
let res = res.await.unwrap();
let res = res.await.unwrap().unwrap();
assert_eq!(res.status(), 200);
}
@ -364,7 +381,9 @@ mod cross_version {
let req = client
.request_builder("/0.5")
.method("POST")
.body(hyper::Body::from(&[1u8; 64 * 1024 + 1][..]))
.body(BoxBody::new(http_body_util::Full::new(Bytes::from(
&[1u8; 64 * 1024 + 1][..],
))))
.unwrap();
let res = client.request_body(req).await;
assert_eq!(res.status(), 533);
@ -386,13 +405,14 @@ mod cross_version {
.await;
let client = test.client;
let (mut tx, body) = hyper::body::Body::channel();
let (mut tx, body) = http_body_util::channel::Channel::<Bytes, Infallible>::new(1024);
let req = client
.request_builder("/0.5")
.method("POST")
.body(body)
.unwrap();
let res = tokio::spawn(async move { client.request_body(req).await });
let fut = client.send_req(req);
let res = tokio::spawn(fut);
// send a 32k chunk
tx.send_data(Bytes::from(&[1u8; 32 * 1024][..]))
.await
@ -406,7 +426,7 @@ mod cross_version {
.await
.expect("the whole body should be read");
drop(tx);
let res = res.await.unwrap();
let res = res.await.unwrap().unwrap();
assert_eq!(res.status(), 533);
}
@ -590,6 +610,8 @@ mod http2 {
}
mod grpc_retry {
use std::convert::Infallible;
use super::*;
use http::header::{HeaderName, HeaderValue};
static GRPC_STATUS: HeaderName = HeaderName::from_static("grpc-status");
@ -613,7 +635,7 @@ mod grpc_retry {
let rsp = Response::builder()
.header(GRPC_STATUS.clone(), header)
.status(200)
.body(hyper::Body::empty())
.body(BoxBody::empty())
.unwrap();
tracing::debug!(headers = ?rsp.headers());
rsp
@ -661,9 +683,16 @@ mod grpc_retry {
let mut trailers = HeaderMap::with_capacity(1);
trailers.insert(GRPC_STATUS.clone(), status);
tracing::debug!(?trailers);
let (mut tx, body) = hyper::body::Body::channel();
let (mut tx, body) =
http_body_util::channel::Channel::<Bytes, Error>::new(1024);
tx.send_trailers(trailers).await.unwrap();
Ok::<_, Error>(Response::builder().status(200).body(body).unwrap())
Ok::<_, Error>(
Response::builder()
.status(200)
.body(body)
.unwrap()
.map(BoxBody::new),
)
}
}
});
@ -704,10 +733,17 @@ mod grpc_retry {
let mut trailers = HeaderMap::with_capacity(1);
trailers.insert(GRPC_STATUS.clone(), GRPC_STATUS_OK.clone());
tracing::debug!(?trailers);
let (mut tx, body) = hyper::body::Body::channel();
let (mut tx, body) =
http_body_util::channel::Channel::<Bytes, Error>::new(1024);
tx.send_data("hello world".into()).await.unwrap();
tx.send_trailers(trailers).await.unwrap();
Ok::<_, Error>(Response::builder().status(200).body(body).unwrap())
Ok::<_, Error>(
Response::builder()
.status(200)
.body(body)
.unwrap()
.map(BoxBody::new),
)
}
}
});
@ -752,13 +788,20 @@ mod grpc_retry {
let mut trailers = HeaderMap::with_capacity(1);
trailers.insert(GRPC_STATUS.clone(), GRPC_STATUS_OK.clone());
tracing::debug!(?trailers);
let (mut tx, body) = hyper::body::Body::channel();
let (mut tx, body) =
http_body_util::channel::Channel::<Bytes, Infallible>::new(1024);
tokio::spawn(async move {
tx.send_data("hello".into()).await.unwrap();
tx.send_data("world".into()).await.unwrap();
tx.send_trailers(trailers).await.unwrap();
});
Ok::<_, Error>(Response::builder().status(200).body(body).unwrap())
Ok::<_, Error>(
Response::builder()
.status(200)
.body(body)
.unwrap()
.map(BoxBody::new),
)
}
}
});
@ -790,21 +833,38 @@ mod grpc_retry {
assert_eq!(retries.load(Ordering::Relaxed), 1);
}
async fn data(body: &mut hyper::Body) -> Bytes {
async fn data<B>(body: &mut B) -> B::Data
where
B: http_body::Body + Unpin,
B::Data: std::fmt::Debug,
B::Error: std::fmt::Debug,
{
use http_body_util::BodyExt;
let data = body
.data()
.frame()
.await
.expect("body data frame must not be eaten")
.unwrap();
.expect("a result")
.expect("a frame")
.into_data()
.expect("a chunk of data");
tracing::info!(?data);
data
}
async fn trailers(body: &mut hyper::Body) -> http::HeaderMap {
async fn trailers<B>(body: &mut B) -> http::HeaderMap
where
B: http_body::Body + Unpin,
B::Error: std::fmt::Debug,
{
use http_body_util::BodyExt;
let trailers = body
.trailers()
.frame()
.await
.expect("trailers future should not fail")
.expect("response should have trailers");
.expect("a result")
.expect("a frame")
.into_trailers()
.ok()
.expect("a trailers frame");
tracing::info!(?trailers);
trailers
}

View File

@ -1,3 +1,5 @@
use linkerd_app_core::svc::http::BoxBody;
use crate::*;
#[tokio::test]
@ -26,10 +28,13 @@ async fn h2_exercise_goaways_connections() {
let (shdn, rx) = shutdown_signal();
let body = Bytes::from(vec![b'1'; RESPONSE_SIZE]);
let body = http_body_util::Full::new(Bytes::from(vec![b'1'; RESPONSE_SIZE]));
let srv = server::http2()
.route_fn("/", move |_req| {
Response::builder().body(body.clone().into()).unwrap()
Response::builder()
.body(body.clone())
.unwrap()
.map(BoxBody::new)
})
.run()
.await;
@ -50,8 +55,8 @@ async fn h2_exercise_goaways_connections() {
.into_iter()
.map(Response::into_body)
.map(|body| {
http_body::Body::collect(body)
.map_ok(http_body::Collected::aggregate)
http_body_util::BodyExt::collect(body)
.map_ok(http_body_util::Collected::aggregate)
// Make sure the bodies weren't cut off
.map_ok(|buf| assert_eq!(buf.remaining(), RESPONSE_SIZE))
})
@ -72,7 +77,7 @@ async fn http1_closes_idle_connections() {
let (shdn, rx) = shutdown_signal();
const RESPONSE_SIZE: usize = 1024 * 16;
let body = Bytes::from(vec![b'1'; RESPONSE_SIZE]);
let body = http_body_util::Full::new(Bytes::from(vec![b'1'; RESPONSE_SIZE]));
let shdn = Arc::new(Mutex::new(Some(shdn)));
let srv = server::http1()
@ -80,7 +85,10 @@ async fn http1_closes_idle_connections() {
// Trigger a shutdown signal while the request is made
// but a response isn't returned yet.
shdn.lock().take().expect("only 1 request").signal();
Response::builder().body(body.clone().into()).unwrap()
Response::builder()
.body(body.clone())
.unwrap()
.map(BoxBody::new)
})
.run()
.await;
@ -101,7 +109,7 @@ async fn tcp_waits_for_proxies_to_close() {
let msg1 = "custom tcp hello\n";
let msg2 = "custom tcp bye";
let srv = server::tcp()
let srv = crate::tcp::server()
// Trigger a shutdown while TCP stream is busy
.accept_fut(move |mut sock| {
async move {
@ -117,7 +125,7 @@ async fn tcp_waits_for_proxies_to_close() {
.await;
let proxy = proxy::new().inbound(srv).shutdown_signal(rx).run().await;
let client = client::tcp(proxy.inbound);
let client = crate::tcp::client(proxy.inbound);
let tcp_client = client.connect().await;

View File

@ -254,7 +254,7 @@ async fn grpc_headers_end() {
assert_eq!(res.status(), 200);
assert_eq!(res.headers()["grpc-status"], "1");
let body = res.into_body();
let bytes = http_body::Body::collect(body)
let bytes = http_body_util::BodyExt::collect(body)
.await
.unwrap()
.to_bytes()

View File

@ -57,9 +57,7 @@ impl Fixture {
let client = client::new(proxy.inbound, "tele.test.svc.cluster.local");
let tcp_dst_labels = metrics::labels().label("direction", "inbound");
let tcp_src_labels = tcp_dst_labels.clone().label("target_addr", orig_dst);
let labels = tcp_dst_labels
.clone()
.label("authority", "tele.test.svc.cluster.local");
let labels = tcp_dst_labels.clone().label("target_port", orig_dst.port());
let tcp_src_labels = tcp_src_labels.label("peer", "src");
let tcp_dst_labels = tcp_dst_labels.label("peer", "dst");
Fixture {
@ -121,7 +119,7 @@ impl TcpFixture {
const BYE_MSG: &'static str = "custom tcp bye";
async fn server() -> server::Listening {
server::tcp()
crate::tcp::server()
.accept(move |read| {
assert_eq!(read, Self::HELLO_MSG.as_bytes());
TcpFixture::BYE_MSG
@ -147,7 +145,7 @@ impl TcpFixture {
.run()
.await;
let client = client::tcp(proxy.inbound);
let client = crate::tcp::client(proxy.inbound);
let metrics = client::http1(proxy.admin, "localhost");
let src_labels = metrics::labels()
@ -186,7 +184,7 @@ impl TcpFixture {
.run()
.await;
let client = client::tcp(proxy.outbound);
let client = crate::tcp::client(proxy.outbound);
let metrics = client::http1(proxy.admin, "localhost");
let src_labels = metrics::labels()
@ -294,7 +292,7 @@ async fn metrics_endpoint_outbound_response_count() {
test_http_count("response_total", Fixture::outbound()).await
}
async fn test_http_count(metric: &str, fixture: impl Future<Output = Fixture>) {
async fn test_http_count(metric_name: &str, fixture: impl Future<Output = Fixture>) {
let _trace = trace_init();
let Fixture {
client,
@ -307,9 +305,13 @@ async fn test_http_count(metric: &str, fixture: impl Future<Output = Fixture>) {
..
} = fixture.await;
let metric = labels.metric(metric);
let metric = labels.metric(metric_name);
assert!(metric.is_not_in(metrics.get("/metrics").await));
let scrape = metrics.get("/metrics").await;
assert!(
metric.is_not_in(scrape),
"{metric:?} should not be in /metrics"
);
info!("client.get(/)");
assert_eq!(client.get("/").await, "hello");
@ -321,6 +323,7 @@ async fn test_http_count(metric: &str, fixture: impl Future<Output = Fixture>) {
mod response_classification {
use super::Fixture;
use crate::*;
use linkerd_app_core::svc::http::BoxBody;
use tracing::info;
const REQ_STATUS_HEADER: &str = "x-test-status-requested";
@ -355,7 +358,7 @@ mod response_classification {
// TODO: tests for grpc statuses
unreachable!("not called in test")
} else {
Response::new("".into())
Response::new(BoxBody::empty())
};
*rsp.status_mut() = status;
rsp
@ -1306,7 +1309,7 @@ async fn metrics_compression() {
let mut body = {
let body = resp.into_body();
http_body::Body::collect(body)
http_body_util::BodyExt::collect(body)
.await
.expect("response body concat")
.aggregate()
@ -1315,9 +1318,9 @@ async fn metrics_compression() {
body.copy_to_bytes(body.remaining()),
));
let mut scrape = String::new();
decoder.read_to_string(&mut scrape).unwrap_or_else(|_| {
panic!("decode gzip (requested Accept-Encoding: {})", encoding)
});
decoder
.read_to_string(&mut scrape)
.unwrap_or_else(|_| panic!("decode gzip (requested Accept-Encoding: {encoding})"));
scrape
}
};

View File

@ -26,7 +26,7 @@ async fn is_valid_json() {
assert!(!json.is_empty());
for obj in json {
println!("{}\n", obj);
println!("{obj}\n");
}
}
@ -53,7 +53,7 @@ async fn query_is_valid_json() {
assert!(!json.is_empty());
for obj in json {
println!("{}\n", obj);
println!("{obj}\n");
}
}
@ -74,12 +74,9 @@ async fn valid_get_does_not_error() {
let json = logs.await.unwrap();
for obj in json {
println!("{}\n", obj);
println!("{obj}\n");
if obj.get("error").is_some() {
panic!(
"expected the log stream to contain no error responses!\njson = {}",
obj
);
panic!("expected the log stream to contain no error responses!\njson = {obj}");
}
}
}
@ -101,12 +98,9 @@ async fn valid_query_does_not_error() {
let json = logs.await.unwrap();
for obj in json {
println!("{}\n", obj);
println!("{obj}\n");
if obj.get("error").is_some() {
panic!(
"expected the log stream to contain no error responses!\njson = {}",
obj
);
panic!("expected the log stream to contain no error responses!\njson = {obj}");
}
}
}
@ -142,9 +136,7 @@ async fn multi_filter() {
level.and_then(|value| value.as_str()),
Some("DEBUG") | Some("INFO") | Some("WARN") | Some("ERROR")
),
"level must be DEBUG, INFO, WARN, or ERROR\n level: {:?}\n json: {:#?}",
level,
obj
"level must be DEBUG, INFO, WARN, or ERROR\n level: {level:?}\n json: {obj:#?}"
);
}
@ -175,9 +167,9 @@ async fn get_log_stream(
let req = client
.request_body(
client
.request_builder(&format!("{}?{}", PATH, filter))
.request_builder(&format!("{PATH}?{filter}"))
.method(http::Method::GET)
.body(hyper::Body::from(filter))
.body(http_body_util::Full::new(Bytes::from(filter)))
.unwrap(),
)
.await;
@ -199,7 +191,7 @@ async fn query_log_stream(
client
.request_builder(PATH)
.method("QUERY")
.body(hyper::Body::from(filter))
.body(http_body_util::Full::new(Bytes::from(filter)))
.unwrap(),
)
.await;
@ -210,19 +202,28 @@ async fn query_log_stream(
/// Spawns a task to collect all the logs in a streaming body and parse them as
/// JSON.
fn collect_logs(
mut body: hyper::Body,
) -> (JoinHandle<Vec<serde_json::Value>>, oneshot::Sender<()>) {
fn collect_logs<B>(mut body: B) -> (JoinHandle<Vec<serde_json::Value>>, oneshot::Sender<()>)
where
B: Body<Data = Bytes> + Send + Unpin + 'static,
B::Error: std::error::Error,
{
use http_body_util::BodyExt;
let (done_tx, done_rx) = oneshot::channel();
let result = tokio::spawn(async move {
let mut result = Vec::new();
let logs = &mut result;
let fut = async move {
while let Some(res) = body.data().await {
while let Some(res) = body.frame().await {
let chunk = match res {
Ok(chunk) => chunk,
Ok(frame) => {
if let Ok(data) = frame.into_data() {
data
} else {
break;
}
}
Err(e) => {
println!("body failed: {}", e);
println!("body failed: {e}");
break;
}
};

View File

@ -80,10 +80,7 @@ impl Test {
.await
};
env.put(
app::env::ENV_INBOUND_DETECT_TIMEOUT,
format!("{:?}", TIMEOUT),
);
env.put(app::env::ENV_INBOUND_DETECT_TIMEOUT, format!("{TIMEOUT:?}"));
(self.set_env)(&mut env);
@ -113,7 +110,7 @@ async fn inbound_timeout() {
let _trace = trace_init();
let (proxy, metrics) = Test::default().run().await;
let client = client::tcp(proxy.inbound);
let client = crate::tcp::client(proxy.inbound);
let _tcp_client = client.connect().await;
@ -127,26 +124,6 @@ async fn inbound_timeout() {
.await;
}
/// Tests that the detect metric is labeled and incremented on I/O error.
#[tokio::test]
async fn inbound_io_err() {
let _trace = trace_init();
let (proxy, metrics) = Test::default().run().await;
let client = client::tcp(proxy.inbound);
let tcp_client = client.connect().await;
tcp_client.write(TcpFixture::HELLO_MSG).await;
drop(tcp_client);
metric(&proxy)
.label("error", "i/o")
.value(1u64)
.assert_in(&metrics)
.await;
}
/// Tests that the detect metric is not incremented when TLS is successfully
/// detected.
#[tokio::test]
@ -167,7 +144,7 @@ async fn inbound_success() {
"foo.ns1.svc.cluster.local",
client_config.clone(),
);
let no_tls_client = client::tcp(proxy.inbound);
let no_tls_client = crate::tcp::client(proxy.inbound);
let metric = metric(&proxy)
.label("error", "tls detection timeout")
@ -192,44 +169,6 @@ async fn inbound_success() {
metric.assert_in(&metrics).await;
}
/// Tests both of the above cases together.
#[tokio::test]
async fn inbound_multi() {
let _trace = trace_init();
let (proxy, metrics) = Test::default().run().await;
let client = client::tcp(proxy.inbound);
let metric = metric(&proxy);
let timeout_metric = metric.clone().label("error", "tls detection timeout");
let io_metric = metric.label("error", "i/o");
let tcp_client = client.connect().await;
tokio::time::sleep(TIMEOUT + Duration::from_millis(15)) // just in case
.await;
timeout_metric.clone().value(1u64).assert_in(&metrics).await;
drop(tcp_client);
let tcp_client = client.connect().await;
tcp_client.write(TcpFixture::HELLO_MSG).await;
drop(tcp_client);
io_metric.clone().value(1u64).assert_in(&metrics).await;
timeout_metric.clone().value(1u64).assert_in(&metrics).await;
let tcp_client = client.connect().await;
tokio::time::sleep(TIMEOUT + Duration::from_millis(15)) // just in case
.await;
io_metric.clone().value(1u64).assert_in(&metrics).await;
timeout_metric.clone().value(2u64).assert_in(&metrics).await;
drop(tcp_client);
}
/// Tests that TLS detect failure metrics are collected for the direct stack.
#[tokio::test]
async fn inbound_direct_multi() {
@ -244,7 +183,7 @@ async fn inbound_direct_multi() {
let proxy = proxy::new().inbound(srv).inbound_direct();
let (proxy, metrics) = Test::new(proxy).run().await;
let client = client::tcp(proxy.inbound);
let client = crate::tcp::client(proxy.inbound);
let metric = metrics::metric(METRIC).label("target_addr", proxy.inbound);
let timeout_metric = metric.clone().label("error", "tls detection timeout");
@ -291,7 +230,7 @@ async fn inbound_invalid_ip() {
.run()
.await;
let client = client::tcp(proxy.inbound);
let client = crate::tcp::client(proxy.inbound);
let metric = metric(&proxy)
.label("error", "unexpected")
.label("target_addr", fake_ip);
@ -354,7 +293,7 @@ async fn inbound_direct_success() {
.await;
let tls_client = client::http1(proxy2.outbound, auth);
let no_tls_client = client::tcp(proxy1.inbound);
let no_tls_client = crate::tcp::client(proxy1.inbound);
let metric = metrics::metric(METRIC)
.label("target_addr", proxy1.inbound)

Some files were not shown because too many files have changed in this diff Show More