From 0264a20191d0d28173b9bb1cab6e076934e3f320 Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Mon, 24 Jun 2024 23:40:22 -0700 Subject: [PATCH 01/16] Upgrade rs-consul to latest http, hyper, opentelemetry --- .github/workflows/format-code.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/main.yml | 4 +- .github/workflows/publish.yml | 6 +- CHANGELOG.md | 9 +++ Cargo.toml | 12 ++-- rust-toolchain | 2 +- src/hyper_wrapper.rs | 1 - src/lib.rs | 92 ++++++++++++++++++++----------- 9 files changed, 84 insertions(+), 46 deletions(-) diff --git a/.github/workflows/format-code.yml b/.github/workflows/format-code.yml index 1c5251f..42693b3 100644 --- a/.github/workflows/format-code.yml +++ b/.github/workflows/format-code.yml @@ -8,7 +8,7 @@ on: jobs: format-code: runs-on: "ubuntu-latest" - container: rust:1.77 + container: rust:1.79 steps: - name: Checkout the code on merge diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 297fb62..9e0d1d5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,7 +9,7 @@ on: jobs: lint: runs-on: "ubuntu-latest" - container: rust:1.77 + container: rust:1.79 steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 911ca6f..5d87f53 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: matrix: features: ["", "--no-default-features --features rustls-native"] runs-on: "ubuntu-latest" - container: rust:1.74 + container: rust:1.79 steps: - uses: actions/checkout@v2 @@ -26,7 +26,7 @@ jobs: matrix: features: ["", "--no-default-features --features rustls-native"] runs-on: "ubuntu-latest" - container: rust:1.77 + container: rust:1.79 services: consul: image: consul:1.11.11 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9841d9e..e2a6b3d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,7 +6,7 @@ on: jobs: test: runs-on: ubuntu-latest - container: rust:1.77 + container: rust:1.79 services: consul: image: consul:1.11.11 @@ -25,7 +25,7 @@ jobs: dry-run: runs-on: ubuntu-latest - container: rust:1.77 + container: rust:1.79 steps: - uses: actions/checkout@v2 @@ -36,7 +36,7 @@ jobs: publish: needs: [test, dry-run] runs-on: ubuntu-latest - container: rust:1.74 + container: rust:1.79 environment: crates-publish steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8afc7bc..be5de48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## Unreleased +## 0.7.0 - 2024-06-25 + +### Changed + +- `opentelemetry` updated to version `0.23` from `0.22`. +- `http` updated to version `1.0` from `0.2`. +- `hyper` updated to version `1.0` from `0.14`. +- `hyper-rustls` updated to version `0.27` from `0.24`. + ## 0.6.0 - 2024-04-01 ### Changed diff --git a/Cargo.toml b/Cargo.toml index c8a9841..c1c15fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rs-consul" -version = "0.6.0" +version = "0.7.0" authors = ["Roblox"] edition = "2021" description = "This crate provides access to a set of strongly typed apis to interact with consul (https://www.consul.io/)" @@ -20,11 +20,13 @@ trace = ["dep:opentelemetry"] [dependencies] base64 = "0.22" futures = "0.3" -http = "0.2" -hyper = { version = "0.14", features = ["full"] } -hyper-rustls = { version = "0.24" } +http = "1" +http-body-util = "0.1" +hyper = { version = "1", features = ["full"] } +hyper-rustls = { version = "0.27" } +hyper-util = { version = "0.1", features = ["client", "client-legacy", "tokio", "http2"] } lazy_static = { version = "1", optional = true } -opentelemetry = { version = "0.22", optional = true } +opentelemetry = { version = "0.23", optional = true } prometheus = { version = "0.13", optional = true } quick-error = "2" serde = { version = "1.0", features = ["derive"] } diff --git a/rust-toolchain b/rust-toolchain index f23daf4..c408301 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.77 \ No newline at end of file +1.79 \ No newline at end of file diff --git a/src/hyper_wrapper.rs b/src/hyper_wrapper.rs index b51425f..9688ede 100644 --- a/src/hyper_wrapper.rs +++ b/src/hyper_wrapper.rs @@ -21,7 +21,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#![cfg(feature = "trace")] use hyper::Version; use opentelemetry::{ global::{BoxedSpan, BoxedTracer}, diff --git a/src/lib.rs b/src/lib.rs index 343bd64..a8d21d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,12 +27,18 @@ SOFTWARE. //! This crate provides access to a set of strongly typed apis to interact with consul (https://www.consul.io/) #![deny(missing_docs)] +use http_body_util::BodyExt; use std::collections::HashMap; +use std::convert::Infallible; use std::time::{Duration, Instant}; use std::{env, str::Utf8Error}; use base64::Engine; -use hyper::{body::Buf, client::HttpConnector, Body, Method}; +use http_body_util::combinators::BoxBody; +use http_body_util::{Empty, Full}; +use hyper::body::Bytes; +use hyper::{body::Buf, Method}; +use hyper_util::client::legacy::{connect::HttpConnector, Builder, Client}; #[cfg(any(feature = "rustls-native", feature = "rustls-webpki"))] #[cfg(feature = "metrics")] use lazy_static::lazy_static; @@ -66,7 +72,7 @@ quick_error! { /// The request was invalid and could not be converted into a proper http request. RequestError(err: http::Error) {} /// The consul server response could not be converted into a proper http response. - ResponseError(err: hyper::Error) {} + ResponseError(err: hyper_util::client::legacy::Error) {} /// The consul server response was invalid. InvalidResponse(err: hyper::Error) {} /// The consul server response could not be deserialized from json. @@ -151,7 +157,7 @@ const GET_SESSION_METHOD_NAME: &str = "get_session"; pub(crate) type Result = std::result::Result; /// The config necessary to create a new consul client. -#[derive(Clone, Debug, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Config { /// The address of the consul server. This must include the protocol to connect over eg. http or https. pub address: String, @@ -160,7 +166,12 @@ pub struct Config { /// The hyper builder for the internal http client. #[serde(skip)] - pub hyper_builder: hyper::client::Builder, + #[serde(default = "default_builder")] + pub hyper_builder: hyper_util::client::legacy::Builder, +} + +fn default_builder() -> Builder { + Builder::new(hyper_util::rt::TokioExecutor::new()) } impl Config { @@ -176,7 +187,7 @@ impl Config { Config { address: addr, token: Some(token), - hyper_builder: Default::default(), + hyper_builder: Builder::new(hyper_util::rt::TokioExecutor::new()), } } } @@ -224,26 +235,26 @@ impl Drop for Lock<'_> { #[derive(Debug)] /// This struct defines the consul client and allows access to the consul api via method syntax. pub struct Consul { - https_client: hyper::Client, Body>, + https_client: Client, BoxBody>, config: Config, #[cfg(feature = "trace")] tracer: BoxedTracer, } -fn https_connector() -> hyper_rustls::HttpsConnector { +fn https_connector() -> Result> { #[cfg(feature = "rustls-webpki")] - return hyper_rustls::HttpsConnectorBuilder::new() + return Ok(hyper_rustls::HttpsConnectorBuilder::new() .with_webpki_roots() .https_or_http() .enable_http1() - .build(); + .build()); #[allow(unreachable_code)] // Clippy doesn't realize if the feature is disabled, this code would execute. - hyper_rustls::HttpsConnectorBuilder::new() - .with_native_roots() + Ok(hyper_rustls::HttpsConnectorBuilder::new() + .with_native_roots()? .https_or_http() .enable_http1() - .build() + .build()) } impl Consul { @@ -251,15 +262,17 @@ impl Consul { /// This is the entry point for this crate. /// #Arguments: /// - [Config](consul::Config) - pub fn new(config: Config) -> Self { - let https = https_connector(); - let https_client = config.hyper_builder.build::<_, hyper::Body>(https); - Consul { + pub fn new(config: Config) -> Result { + let https = https_connector()?; + let https_client = config + .hyper_builder + .build::<_, BoxBody>(https); + Ok(Consul { https_client, config, #[cfg(feature = "trace")] tracer: global::tracer("consul"), - } + }) } /// Reads a key from Consul's KV store. See the [consul docs](https://www.consul.io/api-docs/kv#read-key) for more information. @@ -270,7 +283,12 @@ impl Consul { pub async fn read_key(&self, request: ReadKeyRequest<'_>) -> Result> { let req = self.build_read_key_req(request); let (mut response_body, _index) = self - .execute_request(req, hyper::Body::empty(), None, READ_KEY_METHOD_NAME) + .execute_request( + req, + BoxBody::new(http_body_util::Empty::::new()), + None, + READ_KEY_METHOD_NAME, + ) .await?; let bytes = response_body.copy_to_bytes(response_body.remaining()); serde_json::from_slice::>(&bytes) @@ -310,7 +328,7 @@ impl Consul { let (mut response_body, index) = self .execute_request( req, - Body::from(value), + BoxBody::new(Full::::new(Bytes::from(value))), None, CREATE_OR_UPDATE_KEY_METHOD_NAME, ) @@ -398,7 +416,12 @@ impl Consul { url = add_namespace_and_datacenter(url, request.namespace, request.datacenter); req = req.uri(url); let (mut response_body, _index) = self - .execute_request(req, hyper::Body::empty(), None, DELETE_KEY_METHOD_NAME) + .execute_request( + req, + BoxBody::new(Empty::::new()), + None, + DELETE_KEY_METHOD_NAME, + ) .await?; let bytes = response_body.copy_to_bytes(response_body.remaining()); serde_json::from_slice(&bytes).map_err(ConsulError::ResponseDeserializationFailed) @@ -444,7 +467,7 @@ impl Consul { let (_watch, index) = self .execute_request( lock_index_req, - hyper::Body::empty(), + BoxBody::new(http_body_util::Empty::::new()), None, GET_LOCK_METHOD_NAME, ) @@ -486,7 +509,7 @@ impl Consul { let payload = serde_json::to_string(payload).map_err(ConsulError::InvalidRequest)?; self.execute_request( request, - payload.into(), + BoxBody::new(Full::::new(Bytes::from(payload.into_bytes()))), Some(Duration::from_secs(5)), REGISTER_ENTITY_METHOD_NAME, ) @@ -506,7 +529,7 @@ impl Consul { let payload = serde_json::to_string(payload).map_err(ConsulError::InvalidRequest)?; self.execute_request( request, - payload.into(), + BoxBody::new(Full::::new(Bytes::from(payload.into_bytes()))), Some(Duration::from_secs(5)), DEREGISTER_ENTITY_METHOD_NAME, ) @@ -534,7 +557,7 @@ impl Consul { let (mut response_body, index) = self .execute_request( request, - hyper::Body::empty(), + BoxBody::new(Empty::::new()), query_opts.timeout, GET_ALL_REGISTERED_SERVICE_NAMES_METHOD_NAME, ) @@ -566,7 +589,7 @@ impl Consul { let (mut response_body, index) = self .execute_request( req, - hyper::Body::empty(), + BoxBody::new(Empty::::new()), query_opts.timeout, GET_SERVICE_NODES_METHOD_NAME, ) @@ -684,7 +707,9 @@ impl Consul { let (mut response_body, _index) = self .execute_request( req, - hyper::Body::from(create_session_json), + BoxBody::new(Full::::new(Bytes::from( + create_session_json.into_bytes(), + ))), None, GET_SESSION_METHOD_NAME, ) @@ -718,7 +743,7 @@ impl Consul { async fn execute_request<'a>( &self, req: http::request::Builder, - body: hyper::Body, + body: BoxBody, duration: Option, request_name: &str, ) -> Result<(Box, u64)> { @@ -764,9 +789,12 @@ impl Consul { if status != hyper::StatusCode::OK { record_failure_metric_if_enabled(&method, request_name); - let mut response_body = hyper::body::aggregate(response.into_body()) + let mut response_body = response + .into_body() + .collect() .await - .map_err(|e| ConsulError::UnexpectedResponseCode(status, e.to_string()))?; + .map_err(|e| ConsulError::UnexpectedResponseCode(status, e.to_string()))? + .aggregate(); let bytes = response_body.copy_to_bytes(response_body.remaining()); let resp = std::str::from_utf8(&bytes) .map_err(|e| ConsulError::UnexpectedResponseCode(status, e.to_string()))?; @@ -780,7 +808,7 @@ impl Consul { None => 0, }; - match hyper::body::aggregate(response.into_body()).await { + match response.into_body().collect().await.map(|b| b.aggregate()) { Ok(body) => Ok((Box::new(body), index)), Err(e) => { record_failure_metric_if_enabled(&method, request_name); @@ -974,7 +1002,7 @@ mod tests { .iter() .map(|sn| sn.service.address.clone()) .collect(); - let expected_addresses = vec![ + let expected_addresses = [ "1.1.1.1".to_string(), "2.2.2.2".to_string(), "3.3.3.3".to_string(), @@ -1261,7 +1289,7 @@ mod tests { fn get_client() -> Consul { let conf: Config = Config::from_env(); - Consul::new(conf) + Consul::new(conf).unwrap() } async fn create_or_update_key_value( From f800ef56a295e4abe5b0a23f086e39aaef52841d Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Tue, 25 Jun 2024 21:48:30 -0700 Subject: [PATCH 02/16] Fix possible hang from hyper-util --- src/lib.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index a8d21d0..a90305a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -171,7 +171,21 @@ pub struct Config { } fn default_builder() -> Builder { + // https://github.com/hyperium/hyper/issues/2312 Builder::new(hyper_util::rt::TokioExecutor::new()) + .pool_idle_timeout(std::time::Duration::from_millis(0)) + .pool_max_idle_per_host(0) + .to_owned() +} + +impl Default for Config { + fn default() -> Self { + Config { + address: String::default(), + token: None, + hyper_builder: default_builder(), + } + } } impl Config { From af0841618c1ea6fdd999e1a2d35bd7cc451c50e7 Mon Sep 17 00:00:00 2001 From: Kushagra Udai <112903599+kushudai@users.noreply.github.com> Date: Mon, 1 Jul 2024 00:42:07 -0700 Subject: [PATCH 03/16] Update src/lib.rs --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index a90305a..058049e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,7 +201,7 @@ impl Config { Config { address: addr, token: Some(token), - hyper_builder: Builder::new(hyper_util::rt::TokioExecutor::new()), + hyper_builder: default_builder(), } } } From c824e3adcabc9ab6d47c1b2aaadaff51e3952913 Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Mon, 1 Jul 2024 01:03:58 -0700 Subject: [PATCH 04/16] Remove unused dep --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c1c15fb..7ec5934 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ trace = ["dep:opentelemetry"] # keep this list sorted! [dependencies] base64 = "0.22" -futures = "0.3" http = "1" http-body-util = "0.1" hyper = { version = "1", features = ["full"] } From e5b9c23f1cffda101a9476396ffe765d47125ebb Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Fri, 19 Jul 2024 23:00:24 -0700 Subject: [PATCH 05/16] cleanup --- src/lib.rs | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 54c1c20..765e3c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -296,7 +296,7 @@ impl Consul { /// [ConsulError](consul::ConsulError) describes all possible errors returned by this api. pub async fn read_key(&self, request: ReadKeyRequest<'_>) -> Result> { let req = self.build_read_key_req(request); - let (mut response_body, _index) = self + let (response_body, _index) = self .execute_request( req, BoxBody::new(http_body_util::Empty::::new()), @@ -304,8 +304,7 @@ impl Consul { READ_KEY_METHOD_NAME, ) .await?; - let bytes = response_body.copy_to_bytes(response_body.remaining()); - serde_json::from_slice::>(&bytes) + serde_json::from_reader::<_, Vec>(response_body.reader()) .map_err(ConsulError::ResponseDeserializationFailed)? .into_iter() .map(|mut r| { @@ -339,7 +338,7 @@ impl Consul { ) -> Result<(bool, u64)> { let url = self.build_create_or_update_url(request); let req = hyper::Request::builder().method(Method::PUT).uri(url); - let (mut response_body, index) = self + let (response_body, index) = self .execute_request( req, BoxBody::new(Full::::new(Bytes::from(value))), @@ -347,9 +346,9 @@ impl Consul { CREATE_OR_UPDATE_KEY_METHOD_NAME, ) .await?; - let bytes = response_body.copy_to_bytes(response_body.remaining()); Ok(( - serde_json::from_slice(&bytes).map_err(ConsulError::ResponseDeserializationFailed)?, + serde_json::from_reader(response_body.reader()) + .map_err(ConsulError::ResponseDeserializationFailed)?, index, )) } @@ -429,7 +428,7 @@ impl Consul { url = add_namespace_and_datacenter(url, request.namespace, request.datacenter); req = req.uri(url); - let (mut response_body, _index) = self + let (response_body, _index) = self .execute_request( req, BoxBody::new(Empty::::new()), @@ -437,8 +436,8 @@ impl Consul { DELETE_KEY_METHOD_NAME, ) .await?; - let bytes = response_body.copy_to_bytes(response_body.remaining()); - serde_json::from_slice(&bytes).map_err(ConsulError::ResponseDeserializationFailed) + serde_json::from_reader(response_body.reader()) + .map_err(ConsulError::ResponseDeserializationFailed) } /// Obtains a lock against a specific key in consul. See the [consul docs](https://learn.hashicorp.com/tutorials/consul/application-leader-elections?in=consul/developer-configuration) for more information. @@ -568,7 +567,7 @@ impl Consul { let request = hyper::Request::builder() .method(Method::GET) .uri(uri.clone()); - let (mut response_body, index) = self + let (response_body, index) = self .execute_request( request, BoxBody::new(Empty::::new()), @@ -576,9 +575,9 @@ impl Consul { GET_ALL_REGISTERED_SERVICE_NAMES_METHOD_NAME, ) .await?; - let bytes = response_body.copy_to_bytes(response_body.remaining()); - let service_tags_by_name = serde_json::from_slice::>>(&bytes) - .map_err(ConsulError::ResponseDeserializationFailed)?; + let service_tags_by_name = + serde_json::from_reader::<_, HashMap>>(response_body.reader()) + .map_err(ConsulError::ResponseDeserializationFailed)?; Ok(ResponseMeta { response: service_tags_by_name.keys().cloned().collect(), @@ -600,7 +599,7 @@ impl Consul { ) -> Result> { let query_opts = query_opts.unwrap_or_default(); let req = self.build_get_service_nodes_req(request, &query_opts); - let (mut response_body, index) = self + let (response_body, index) = self .execute_request( req, BoxBody::new(Empty::::new()), @@ -608,9 +607,9 @@ impl Consul { GET_SERVICE_NODES_METHOD_NAME, ) .await?; - let bytes = response_body.copy_to_bytes(response_body.remaining()); - let response = serde_json::from_slice::(&bytes) - .map_err(ConsulError::ResponseDeserializationFailed)?; + let response = + serde_json::from_reader::<_, GetServiceNodesResponse>(response_body.reader()) + .map_err(ConsulError::ResponseDeserializationFailed)?; Ok(ResponseMeta { response, index }) } @@ -718,7 +717,7 @@ impl Consul { req = req.uri(url); let create_session_json = serde_json::to_string(&session_req).map_err(ConsulError::InvalidRequest)?; - let (mut response_body, _index) = self + let (response_body, _index) = self .execute_request( req, BoxBody::new(Full::::new(Bytes::from( @@ -728,8 +727,8 @@ impl Consul { GET_SESSION_METHOD_NAME, ) .await?; - let bytes = response_body.copy_to_bytes(response_body.remaining()); - serde_json::from_slice(&bytes).map_err(ConsulError::ResponseDeserializationFailed) + serde_json::from_reader(response_body.reader()) + .map_err(ConsulError::ResponseDeserializationFailed) } fn build_get_service_nodes_req( @@ -1027,10 +1026,9 @@ mod tests { let tags: Vec = response .iter() - .map(|sn| sn.service.tags.clone().into_iter()) - .flatten() + .flat_map(|sn| sn.service.tags.clone().into_iter()) .collect(); - let expected_tags = vec![ + let expected_tags = [ "first".to_string(), "second".to_string(), "third".to_string(), From 9ffd39dc44a2e6a8e10bd2fc644cdd2807abe0a7 Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Fri, 19 Jul 2024 23:16:02 -0700 Subject: [PATCH 06/16] Upgrade test, changelog --- CHANGELOG.md | 4 +++- Cargo.toml | 2 +- src/lib.rs | 11 +++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be5de48..3d40fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Changed -- `opentelemetry` updated to version `0.23` from `0.22`. +- `opentelemetry` updated to version `0.24` from `0.22`. - `http` updated to version `1.0` from `0.2`. - `hyper` updated to version `1.0` from `0.14`. - `hyper-rustls` updated to version `0.27` from `0.24`. +- `get_service_nodes` now supports tags thanks to @gautamg795 +- `read_key` now also returns the index thanks to @badalex ## 0.6.0 - 2024-04-01 diff --git a/Cargo.toml b/Cargo.toml index 7ec5934..31f3460 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ hyper = { version = "1", features = ["full"] } hyper-rustls = { version = "0.27" } hyper-util = { version = "0.1", features = ["client", "client-legacy", "tokio", "http2"] } lazy_static = { version = "1", optional = true } -opentelemetry = { version = "0.23", optional = true } +opentelemetry = { version = "0.24", optional = true } prometheus = { version = "0.13", optional = true } quick-error = "2" serde = { version = "1.0", features = ["derive"] } diff --git a/src/lib.rs b/src/lib.rs index 246e662..1de0f00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -961,8 +961,15 @@ mod tests { let res = create_or_update_key_value(&consul, key, string_value).await; assert_expected_result_with_index(res); - let res = read_key(&consul, key).await; - verify_single_value_matches(res, string_value); + let res = read_key(&consul, key).await.unwrap(); + let index = res.index; + verify_single_value_matches(Ok(res), string_value); + + let res = read_key(&consul, key).await.unwrap(); + assert_eq!(res.index, index); + create_or_update_key_value(&consul, key, "This is a new test").await.unwrap(); + let res = read_key(&consul, key).await.unwrap(); + assert!(res.index > index); } #[tokio::test(flavor = "multi_thread")] From 90cf56e2257d25fcbd4c7f2e027bfd9c6c547519 Mon Sep 17 00:00:00 2001 From: GitHub Action Bot Date: Sat, 20 Jul 2024 06:16:50 +0000 Subject: [PATCH 07/16] Commit from GitHub Actions (Format Code) --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 1de0f00..382c343 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -967,7 +967,9 @@ mod tests { let res = read_key(&consul, key).await.unwrap(); assert_eq!(res.index, index); - create_or_update_key_value(&consul, key, "This is a new test").await.unwrap(); + create_or_update_key_value(&consul, key, "This is a new test") + .await + .unwrap(); let res = read_key(&consul, key).await.unwrap(); assert!(res.index > index); } From 9739dbed65771bfb104f33dbf43cd65de59da81f Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Fri, 19 Jul 2024 23:18:43 -0700 Subject: [PATCH 08/16] Better test --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 1de0f00..c02d57f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -967,6 +967,8 @@ mod tests { let res = read_key(&consul, key).await.unwrap(); assert_eq!(res.index, index); + create_or_update_key_value(&consul, key, string_value).await.unwrap(); + assert_eq!(res.index, index); create_or_update_key_value(&consul, key, "This is a new test").await.unwrap(); let res = read_key(&consul, key).await.unwrap(); assert!(res.index > index); From c452ee2420b40e90c70f5a2dd49c305e5f141545 Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Sat, 20 Jul 2024 12:15:20 -0700 Subject: [PATCH 09/16] Change default and add ring --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 31f3460..3607644 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ license-file = "LICENSE" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -default = ["rustls-native"] +default = ["rustls-webpki"] metrics = ["prometheus", "lazy_static"] rustls-native = ["hyper-rustls/rustls-native-certs"] rustls-webpki = ["hyper-rustls/webpki-roots"] @@ -22,7 +22,7 @@ base64 = "0.22" http = "1" http-body-util = "0.1" hyper = { version = "1", features = ["full"] } -hyper-rustls = { version = "0.27" } +hyper-rustls = { version = "0.27", features = ["ring"] } hyper-util = { version = "0.1", features = ["client", "client-legacy", "tokio", "http2"] } lazy_static = { version = "1", optional = true } opentelemetry = { version = "0.24", optional = true } From 4eff4f50e7dac7bc4a52f58a6ea8ab3c115495ab Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Sat, 20 Jul 2024 12:20:17 -0700 Subject: [PATCH 10/16] Try --- Cargo.toml | 3 +++ src/lib.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 3607644..92b616f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,6 @@ slog-scope = "4" smart-default = "0.7" tokio = { version = "1", features = ["full"] } ureq = { version = "2", features = ["json"] } + +[dev-dependencies] +rustls = { version = "0.23", features = ["ring"] } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 0ad1449..d292d02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1334,6 +1334,7 @@ mod tests { } fn get_client() -> Consul { + rustls::crypto::ring::default_provider().install_default().expect("Failed to install rustls crypto provider"); let conf: Config = Config::from_env(); Consul::new(conf).unwrap() } From b04f308a5b91a402b0748daf5649dcbe07183859 Mon Sep 17 00:00:00 2001 From: GitHub Action Bot Date: Sat, 20 Jul 2024 19:20:57 +0000 Subject: [PATCH 11/16] Commit from GitHub Actions (Format Code) --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d292d02..7d75ff9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1334,7 +1334,9 @@ mod tests { } fn get_client() -> Consul { - rustls::crypto::ring::default_provider().install_default().expect("Failed to install rustls crypto provider"); + rustls::crypto::ring::default_provider() + .install_default() + .expect("Failed to install rustls crypto provider"); let conf: Config = Config::from_env(); Consul::new(conf).unwrap() } From 881cb1bb904848cdd6b489f0650bf817ea3e169d Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Sat, 20 Jul 2024 12:26:29 -0700 Subject: [PATCH 12/16] Rerun --- Cargo.toml | 2 +- src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 92b616f..b315332 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,4 +36,4 @@ tokio = { version = "1", features = ["full"] } ureq = { version = "2", features = ["json"] } [dev-dependencies] -rustls = { version = "0.23", features = ["ring"] } \ No newline at end of file +rustls = { version = "0.23", features = ["ring"] } diff --git a/src/lib.rs b/src/lib.rs index 7d75ff9..229d25e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -949,6 +949,7 @@ fn record_duration_metric_if_enabled(_method: &Method, _function: &str, _duratio mod tests { use std::time::Duration; + use rustls::crypto::ring::default_provider; use tokio::time::sleep; use super::*; @@ -1334,7 +1335,7 @@ mod tests { } fn get_client() -> Consul { - rustls::crypto::ring::default_provider() + default_provider() .install_default() .expect("Failed to install rustls crypto provider"); let conf: Config = Config::from_env(); From 13f05b8bb0123e36d31dea082dbee8331a51772c Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Sat, 20 Jul 2024 12:39:48 -0700 Subject: [PATCH 13/16] Fix non-additive features --- .github/workflows/main.yml | 2 +- CHANGELOG.md | 1 + Cargo.toml | 9 ++------- src/lib.rs | 15 +-------------- 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c0af32c..5d1766f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: test: strategy: matrix: - features: ["", "--no-default-features --features rustls-native"] + features: [""] runs-on: "ubuntu-latest" container: rust:1.79 services: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d40fb4..6dfbdfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - `hyper-rustls` updated to version `0.27` from `0.24`. - `get_service_nodes` now supports tags thanks to @gautamg795 - `read_key` now also returns the index thanks to @badalex +- Removed `rustls-native-roots` feature and now defaults to `rustls-webpki-roots`. This addresses the bug that features were not additive. ## 0.6.0 - 2024-04-01 diff --git a/Cargo.toml b/Cargo.toml index b315332..bc71f88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,8 @@ license-file = "LICENSE" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -default = ["rustls-webpki"] +default = [] metrics = ["prometheus", "lazy_static"] -rustls-native = ["hyper-rustls/rustls-native-certs"] -rustls-webpki = ["hyper-rustls/webpki-roots"] trace = ["dep:opentelemetry"] # keep this list sorted! @@ -22,7 +20,7 @@ base64 = "0.22" http = "1" http-body-util = "0.1" hyper = { version = "1", features = ["full"] } -hyper-rustls = { version = "0.27", features = ["ring"] } +hyper-rustls = { version = "0.27", features = ["webpki-roots"] } hyper-util = { version = "0.1", features = ["client", "client-legacy", "tokio", "http2"] } lazy_static = { version = "1", optional = true } opentelemetry = { version = "0.24", optional = true } @@ -34,6 +32,3 @@ slog-scope = "4" smart-default = "0.7" tokio = { version = "1", features = ["full"] } ureq = { version = "2", features = ["json"] } - -[dev-dependencies] -rustls = { version = "0.23", features = ["ring"] } diff --git a/src/lib.rs b/src/lib.rs index 229d25e..7577f8a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,6 @@ use http_body_util::{Empty, Full}; use hyper::body::Bytes; use hyper::{body::Buf, Method}; use hyper_util::client::legacy::{connect::HttpConnector, Builder, Client}; -#[cfg(any(feature = "rustls-native", feature = "rustls-webpki"))] #[cfg(feature = "metrics")] use lazy_static::lazy_static; use quick_error::quick_error; @@ -256,16 +255,8 @@ pub struct Consul { } fn https_connector() -> Result> { - #[cfg(feature = "rustls-webpki")] - return Ok(hyper_rustls::HttpsConnectorBuilder::new() - .with_webpki_roots() - .https_or_http() - .enable_http1() - .build()); - #[allow(unreachable_code)] - // Clippy doesn't realize if the feature is disabled, this code would execute. Ok(hyper_rustls::HttpsConnectorBuilder::new() - .with_native_roots()? + .with_webpki_roots() .https_or_http() .enable_http1() .build()) @@ -949,7 +940,6 @@ fn record_duration_metric_if_enabled(_method: &Method, _function: &str, _duratio mod tests { use std::time::Duration; - use rustls::crypto::ring::default_provider; use tokio::time::sleep; use super::*; @@ -1335,9 +1325,6 @@ mod tests { } fn get_client() -> Consul { - default_provider() - .install_default() - .expect("Failed to install rustls crypto provider"); let conf: Config = Config::from_env(); Consul::new(conf).unwrap() } From 348553cc438296c39ca3aad401967e7b56b32687 Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Sat, 20 Jul 2024 12:48:59 -0700 Subject: [PATCH 14/16] Missed one --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5d1766f..a6364d1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: build: strategy: matrix: - features: ["", "--no-default-features --features rustls-native"] + features: [""] runs-on: "ubuntu-latest" container: rust:1.79 From 2c42dbbae37480c99c0502eb4b53ef98ace7ea06 Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Sat, 20 Jul 2024 13:01:47 -0700 Subject: [PATCH 15/16] Fix features --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index bc71f88..678f5c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ base64 = "0.22" http = "1" http-body-util = "0.1" hyper = { version = "1", features = ["full"] } -hyper-rustls = { version = "0.27", features = ["webpki-roots"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["webpki-roots", "ring", "http1"] } hyper-util = { version = "0.1", features = ["client", "client-legacy", "tokio", "http2"] } lazy_static = { version = "1", optional = true } opentelemetry = { version = "0.24", optional = true } From 77b202e5e5e3bf38ec68e90dd52f65eec247572d Mon Sep 17 00:00:00 2001 From: Kushagra Udai Date: Sat, 20 Jul 2024 13:16:47 -0700 Subject: [PATCH 16/16] Changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dfbdfd..c7df596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - `hyper-rustls` updated to version `0.27` from `0.24`. - `get_service_nodes` now supports tags thanks to @gautamg795 - `read_key` now also returns the index thanks to @badalex -- Removed `rustls-native-roots` feature and now defaults to `rustls-webpki-roots`. This addresses the bug that features were not additive. +- Allow configuring `Consul` with a custom http client thanks to @LeonHartley +- Removed `rustls-native-roots` feature and now defaults to `rustls-webpki-roots` (which has been removed). This addresses the bug that features were not additive. ## 0.6.0 - 2024-04-01