From a2a08467dd9090a6cf4ab6ac143e07b7ed028f9a Mon Sep 17 00:00:00 2001 From: "Javier G. Sogo" Date: Tue, 26 Aug 2025 10:55:17 +0200 Subject: [PATCH 1/2] test: Test IBMCloudTokenProvider renew network call Signed-off-by: Javier G. Sogo --- .secrets.baseline | 20 ++++++++++++-- src/network/token_provider.rs | 49 +++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 883aa3b..81faec9 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2025-08-25T10:36:44Z", + "generated_at": "2025-08-26T08:55:11Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -80,6 +80,7 @@ "src/client/app_configuration_ibm_cloud.rs": [ { "hashed_secret": "fb34629c9af1ed4045b5d6f287426276b2be3a1e", + "is_secret": false, "is_verified": false, "line_number": 43, "type": "Secret Keyword", @@ -89,6 +90,7 @@ "src/lib.rs": [ { "hashed_secret": "df1431b489758b92c84bdec3c9283b96066a44b8", + "is_secret": false, "is_verified": false, "line_number": 57, "type": "Secret Keyword", @@ -99,7 +101,21 @@ { "hashed_secret": "91271e4ebcf7a9793e252299b9a2c77c8d964325", "is_verified": false, - "line_number": 51, + "line_number": 52, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "fb34629c9af1ed4045b5d6f287426276b2be3a1e", + "is_verified": false, + "line_number": 56, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "3e4bdbe0b80e63c22b178576e906810777387b50", + "is_verified": false, + "line_number": 196, "type": "Secret Keyword", "verified_result": null } diff --git a/src/network/token_provider.rs b/src/network/token_provider.rs index 33abd3b..c40116f 100644 --- a/src/network/token_provider.rs +++ b/src/network/token_provider.rs @@ -43,15 +43,21 @@ impl AccessToken { #[derive(Debug)] pub(crate) struct IBMCloudTokenProvider { + endpoint: String, apikey: String, access_token: RwLock, } impl IBMCloudTokenProvider { pub fn new(apikey: &str) -> Self { + IBMCloudTokenProvider::new_with_endpoint(apikey, "https://iam.cloud.ibm.com/identity/token") + } + + fn new_with_endpoint(apikey: &str, endpoint: &str) -> Self { Self { apikey: apikey.to_string(), access_token: RwLock::default(), + endpoint: endpoint.to_owned(), } } @@ -84,7 +90,7 @@ impl IBMCloudTokenProvider { let client = Client::new(); let new_token = client - .post("https://iam.cloud.ibm.com/identity/token") + .post(&self.endpoint) .header("Accept", "application/json") .form(&form_data) .send() @@ -123,8 +129,12 @@ impl TokenProvider for IBMCloudTokenProvider { #[cfg(test)] mod tests { + use super::*; + use httpmock::Method::POST; + use httpmock::MockServer; + #[test] fn test_access_token() { let mut access_token = AccessToken::default(); @@ -140,7 +150,7 @@ mod tests { } #[test] - fn test_ibm_cloud_token_provider() { + fn test_ibm_cloud_token_provider_expiration_logic() { let provider = IBMCloudTokenProvider::new("apikey"); assert!(provider.expired()); @@ -171,4 +181,39 @@ mod tests { assert_eq!(IBMCloudTokenProvider::safe_expires_in(0), 0); assert_eq!(IBMCloudTokenProvider::safe_expires_in(1), 1); } + + #[test] + fn test_ibm_cloud_token_provider_renew_call() { + let endpoint = "/give/me/a/token"; + let apikey = "12345"; + + let server = MockServer::start(); + let mock = server.mock(|when, then| { + when.method(POST) + .path(endpoint) + .header("Accept", "application/json") + .x_www_form_urlencoded_tuple("reponse_type", "cloud_iam") + .x_www_form_urlencoded_tuple("grant_type", "urn:ibm:params:oauth:grant-type:apikey") + .x_www_form_urlencoded_tuple("apikey", apikey); + then.status(200) + .header("content-type", "application/json") + .json_body(serde_json::json!( + { + "access_token": "the-new-token", + "expires_in": 60 + } + )); + }); + + let token_provider = IBMCloudTokenProvider::new_with_endpoint( + apikey, + &std::format!("http://{}:{}{}", server.host(), server.port(), endpoint), + ); + assert_eq!(token_provider.access_token.read().unwrap().token, ""); + assert_eq!(token_provider.access_token.read().unwrap().expiration, 0); + + let token = token_provider.get_access_token(); + mock.assert(); + assert_eq!(token.unwrap(), "the-new-token"); + } } From afd936694b57566db22552efc69f67edc5310efc Mon Sep 17 00:00:00 2001 From: "Javier G. Sogo" Date: Fri, 26 Sep 2025 12:20:58 +0200 Subject: [PATCH 2/2] adapt to new versions Signed-off-by: Javier G. Sogo --- src/network/token_provider.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/token_provider.rs b/src/network/token_provider.rs index c40116f..ac1163d 100644 --- a/src/network/token_provider.rs +++ b/src/network/token_provider.rs @@ -192,9 +192,9 @@ mod tests { when.method(POST) .path(endpoint) .header("Accept", "application/json") - .x_www_form_urlencoded_tuple("reponse_type", "cloud_iam") - .x_www_form_urlencoded_tuple("grant_type", "urn:ibm:params:oauth:grant-type:apikey") - .x_www_form_urlencoded_tuple("apikey", apikey); + .form_urlencoded_tuple("reponse_type", "cloud_iam") + .form_urlencoded_tuple("grant_type", "urn:ibm:params:oauth:grant-type:apikey") + .form_urlencoded_tuple("apikey", apikey); then.status(200) .header("content-type", "application/json") .json_body(serde_json::json!(