diff --git a/0001-providers-packet-use-stored-client-for-boot-checkin.patch b/0001-providers-packet-use-stored-client-for-boot-checkin.patch new file mode 100644 index 0000000..258e150 --- /dev/null +++ b/0001-providers-packet-use-stored-client-for-boot-checkin.patch @@ -0,0 +1,79 @@ +From f6799a3852ab6145a7bb62b2ec8bc8cd657623b1 Mon Sep 17 00:00:00 2001 +From: Benjamin Gilbert +Date: Mon, 20 Mar 2023 01:08:04 -0400 +Subject: [PATCH 1/6] providers/packet: use stored client for boot checkin + +Store the retry::Client on the PacketProvider and use it for boot checkin +to ease testing. +--- + src/providers/packet/mock_tests.rs | 7 +++++-- + src/providers/packet/mod.rs | 6 +++--- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/src/providers/packet/mock_tests.rs b/src/providers/packet/mock_tests.rs +index d22543ceda92..ef26be4c7759 100644 +--- a/src/providers/packet/mock_tests.rs ++++ b/src/providers/packet/mock_tests.rs +@@ -3,6 +3,7 @@ use mockito::{self, Matcher}; + + #[test] + fn test_boot_checkin() { ++ let client = crate::retry::Client::try_new().unwrap().max_retries(0); + let data = packet::PacketData { + id: String::new(), + hostname: String::new(), +@@ -19,7 +20,10 @@ fn test_boot_checkin() { + error: None, + phone_home_url: mockito::server_url(), + }; +- let provider = packet::PacketProvider { data }; ++ let provider = packet::PacketProvider { ++ client: client.clone(), ++ data, ++ }; + + let mock = mockito::mock("POST", "/") + .match_header( +@@ -37,7 +41,6 @@ fn test_boot_checkin() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); + packet::PacketProvider::fetch_content(Some(client)).unwrap_err(); + } + +diff --git a/src/providers/packet/mod.rs b/src/providers/packet/mod.rs +index be180a546583..98a4018581b4 100644 +--- a/src/providers/packet/mod.rs ++++ b/src/providers/packet/mod.rs +@@ -90,6 +90,7 @@ struct PacketAddressInfo { + + #[derive(Clone, Debug)] + pub struct PacketProvider { ++ client: retry::Client, + data: PacketData, + } + +@@ -113,7 +114,7 @@ impl PacketProvider { + .send()? + .ok_or_else(|| anyhow!("metadata endpoint unreachable"))?; + +- Ok(Self { data }) ++ Ok(Self { client, data }) + } + + #[cfg(test)] +@@ -386,9 +387,8 @@ impl MetadataProvider for PacketProvider { + } + + fn boot_checkin(&self) -> Result<()> { +- let client = retry::Client::try_new()?; + let url = self.data.phone_home_url.clone(); +- client.post(retry::Json, url, None).dispatch_post()?; ++ self.client.post(retry::Json, url, None).dispatch_post()?; + Ok(()) + } + } +-- +2.39.2 + diff --git a/0002-providers-microsoft-use-stored-client-for-all-fetche.patch b/0002-providers-microsoft-use-stored-client-for-all-fetche.patch new file mode 100644 index 0000000..ed444fc --- /dev/null +++ b/0002-providers-microsoft-use-stored-client-for-all-fetche.patch @@ -0,0 +1,67 @@ +From 29c4681ccdb7f8b09e4fc12bc98d184c63e1d0b4 Mon Sep 17 00:00:00 2001 +From: Benjamin Gilbert +Date: Mon, 20 Mar 2023 01:33:10 -0400 +Subject: [PATCH 2/6] providers/microsoft: use stored client for all fetches + +Be sure to use any custom settings on the stored client. +--- + src/providers/microsoft/azure/mod.rs | 8 ++++++-- + src/providers/microsoft/azurestack/mod.rs | 7 ++++--- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/src/providers/microsoft/azure/mod.rs b/src/providers/microsoft/azure/mod.rs +index a3582ae68be7..1d2803c797c3 100644 +--- a/src/providers/microsoft/azure/mod.rs ++++ b/src/providers/microsoft/azure/mod.rs +@@ -338,7 +338,9 @@ impl Azure { + const NAME_URL: &str = "metadata/instance/compute/name?api-version=2017-08-01&format=text"; + let url = format!("{}/{}", Self::metadata_endpoint(), NAME_URL); + +- let name = retry::Client::try_new()? ++ let name = self ++ .client ++ .clone() + .header( + HeaderName::from_static("metadata"), + HeaderValue::from_static("true"), +@@ -354,7 +356,9 @@ impl Azure { + "metadata/instance/compute/vmSize?api-version=2017-08-01&format=text"; + let url = format!("{}/{}", Self::metadata_endpoint(), VMSIZE_URL); + +- let vmsize = retry::Client::try_new()? ++ let vmsize = self ++ .client ++ .clone() + .header( + HeaderName::from_static("metadata"), + HeaderValue::from_static("true"), +diff --git a/src/providers/microsoft/azurestack/mod.rs b/src/providers/microsoft/azurestack/mod.rs +index a0552fbc6a69..04974398ee40 100644 +--- a/src/providers/microsoft/azurestack/mod.rs ++++ b/src/providers/microsoft/azurestack/mod.rs +@@ -168,10 +168,11 @@ impl AzureStack { + .ok_or_else(|| anyhow!("failed to get goal state: not found response")) + } + +- fn fetch_identity() -> Result { ++ fn fetch_identity(&self) -> Result { + const NAME_URL: &str = "Microsoft.Compute/identity?api-version=2019-03-11"; + let url = format!("{}/{}", Self::metadata_endpoint(), NAME_URL); +- retry::Client::try_new()? ++ self.client ++ .clone() + .header( + HeaderName::from_static("metadata"), + HeaderValue::from_static("true"), +@@ -306,7 +307,7 @@ impl AzureStack { + } + + fn fetch_hostname(&self) -> Result> { +- let instance_metadata = AzureStack::fetch_identity()?; ++ let instance_metadata = self.fetch_identity()?; + Ok(Some(instance_metadata.vm_name)) + } + +-- +2.39.2 + diff --git a/0003-providers-microsoft-import-crate-retry.patch b/0003-providers-microsoft-import-crate-retry.patch new file mode 100644 index 0000000..a36dc0d --- /dev/null +++ b/0003-providers-microsoft-import-crate-retry.patch @@ -0,0 +1,87 @@ +From 1e46b818717d250dc3e0a43a0680e919f7c1c3df Mon Sep 17 00:00:00 2001 +From: Benjamin Gilbert +Date: Mon, 20 Mar 2023 02:32:15 -0400 +Subject: [PATCH 3/6] providers/microsoft: import crate::retry + +--- + src/providers/microsoft/azure/mock_tests.rs | 7 ++++--- + src/providers/microsoft/azurestack/mock_tests.rs | 7 ++++--- + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/src/providers/microsoft/azure/mock_tests.rs b/src/providers/microsoft/azure/mock_tests.rs +index 93682012554b..476555dc6368 100644 +--- a/src/providers/microsoft/azure/mock_tests.rs ++++ b/src/providers/microsoft/azure/mock_tests.rs +@@ -1,4 +1,5 @@ + use crate::providers::{microsoft::azure, MetadataProvider}; ++use crate::retry; + use mockito::{self, Matcher}; + + /// Response body for goalstate (with certificates endpoint). +@@ -135,7 +136,7 @@ fn test_boot_checkin() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new().unwrap().max_retries(0); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + +@@ -163,7 +164,7 @@ fn test_hostname() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new().unwrap().max_retries(0); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + +@@ -192,7 +193,7 @@ fn test_vmsize() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new().unwrap().max_retries(0); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + +diff --git a/src/providers/microsoft/azurestack/mock_tests.rs b/src/providers/microsoft/azurestack/mock_tests.rs +index 8c5a0d26399e..655908237337 100644 +--- a/src/providers/microsoft/azurestack/mock_tests.rs ++++ b/src/providers/microsoft/azurestack/mock_tests.rs +@@ -1,4 +1,5 @@ + use crate::providers::{microsoft::azurestack, MetadataProvider}; ++use crate::retry; + use mockito::{self, Matcher}; + + /// Response body for goalstate (with certificates endpoint). +@@ -135,7 +136,7 @@ fn test_boot_checkin() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new().unwrap().max_retries(0); + azurestack::AzureStack::with_client(Some(client)).unwrap_err(); + } + +@@ -164,7 +165,7 @@ fn test_identity() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new().unwrap().max_retries(0); + azurestack::AzureStack::with_client(Some(client)).unwrap_err(); + } + +@@ -193,7 +194,7 @@ fn test_hostname() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new().unwrap().max_retries(0); + azurestack::AzureStack::with_client(Some(client)).unwrap_err(); + } + +-- +2.39.2 + diff --git a/0004-retry-client-move-URL-parsing-into-helper-function.patch b/0004-retry-client-move-URL-parsing-into-helper-function.patch new file mode 100644 index 0000000..fdfb2df --- /dev/null +++ b/0004-retry-client-move-URL-parsing-into-helper-function.patch @@ -0,0 +1,54 @@ +From feda37277c361a29a67ab2549f8fe292c35429dd Mon Sep 17 00:00:00 2001 +From: Benjamin Gilbert +Date: Sun, 19 Mar 2023 23:55:38 -0400 +Subject: [PATCH 4/6] retry/client: move URL parsing into helper function + +--- + src/retry/client.rs | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/src/retry/client.rs b/src/retry/client.rs +index a94c4ec7f09b..e113fe4bc69a 100644 +--- a/src/retry/client.rs ++++ b/src/retry/client.rs +@@ -213,7 +213,7 @@ where + where + T: for<'de> serde::Deserialize<'de>, + { +- let url = reqwest::Url::parse(self.url.as_str()).context("failed to parse uri")?; ++ let url = self.parse_url()?; + let mut req = blocking::Request::new(Method::GET, url); + req.headers_mut().extend(self.headers.clone().into_iter()); + +@@ -227,7 +227,7 @@ where + where + T: for<'de> serde::Deserialize<'de>, + { +- let url = reqwest::Url::parse(self.url.as_str()).context("failed to parse uri")?; ++ let url = self.parse_url()?; + + self.retry.clone().retry(|attempt| { + let mut builder = blocking::Client::new() +@@ -254,7 +254,7 @@ where + } + + pub fn dispatch_post(self) -> Result { +- let url = reqwest::Url::parse(self.url.as_str()).context("failed to parse uri")?; ++ let url = self.parse_url()?; + + self.retry.clone().retry(|attempt| { + let mut builder = blocking::Client::new() +@@ -308,6 +308,10 @@ where + } + } + } ++ ++ fn parse_url(&self) -> Result { ++ reqwest::Url::parse(self.url.as_str()).context("failed to parse uri") ++ } + } + + /// Reqwests Request struct doesn't implement `Clone`, +-- +2.39.2 + diff --git a/0005-providers-move-endpoint-mocking-into-retry-Client.patch b/0005-providers-move-endpoint-mocking-into-retry-Client.patch new file mode 100644 index 0000000..b7a7fe9 --- /dev/null +++ b/0005-providers-move-endpoint-mocking-into-retry-Client.patch @@ -0,0 +1,1047 @@ +From 6da8cac456dc6cf8a53f99ad9c46b5fccb010c20 Mon Sep 17 00:00:00 2001 +From: Benjamin Gilbert +Date: Mon, 20 Mar 2023 02:00:01 -0400 +Subject: [PATCH 5/6] providers/*: move endpoint mocking into retry::Client + +Rather than conditionally compiling a different endpoint_for() when +building tests, teach retry::Client to override the scheme/host/port of +request URLs from a configured mock base URL, then use such an override +from tests. This allows configuring the mock server URL. + +Since we no longer have separate code paths for generating URLs during +test, this changes the mocked paths in certain providers. Update them to +match the production URLs. +--- + src/providers/aliyun/mock_tests.rs | 41 ++++++++++------- + src/providers/aliyun/mod.rs | 9 ---- + src/providers/aws/mock_tests.rs | 38 ++++++++------- + src/providers/aws/mod.rs | 9 ---- + src/providers/cloudstack/mock_tests.rs | 10 +++- + src/providers/cloudstack/network.rs | 4 +- + src/providers/exoscale/mock_tests.rs | 35 ++++++++------ + src/providers/exoscale/mod.rs | 7 --- + src/providers/gcp/mock_tests.rs | 18 +++++--- + src/providers/gcp/mod.rs | 9 ---- + src/providers/microsoft/azure/mock_tests.rs | 46 ++++++++++++++----- + src/providers/microsoft/azure/mod.rs | 15 +----- + .../microsoft/azurestack/mock_tests.rs | 31 +++++++++---- + src/providers/microsoft/azurestack/mod.rs | 15 +----- + src/providers/openstack/mock_tests.rs | 18 +++++--- + src/providers/openstack/network.rs | 7 --- + src/providers/packet/mock_tests.rs | 16 +++++-- + src/providers/packet/mod.rs | 10 +--- + src/providers/vultr/mock_tests.rs | 23 ++++++---- + src/providers/vultr/mod.rs | 9 ---- + src/retry/client.rs | 37 ++++++++++++++- + 21 files changed, 224 insertions(+), 183 deletions(-) + +diff --git a/src/providers/aliyun/mock_tests.rs b/src/providers/aliyun/mock_tests.rs +index cbd2e0c153a5..55c795bb2592 100644 +--- a/src/providers/aliyun/mock_tests.rs ++++ b/src/providers/aliyun/mock_tests.rs +@@ -4,11 +4,14 @@ use mockito; + + #[test] + fn basic_hostname() { +- let ep = "/hostname"; ++ let ep = "/latest/meta-data/hostname"; + let hostname = "test-hostname"; + + let mut provider = aliyun::AliyunProvider::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + + { + let _m503 = mockito::mock("GET", ep).with_status(503).create(); +@@ -46,18 +49,21 @@ fn basic_hostname() { + #[test] + fn basic_pubkeys() { + let mut provider = aliyun::AliyunProvider::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + + // Setup two entries with identical content, in order to test de-dup. +- let _m_keys = mockito::mock("GET", "/public-keys/") ++ let _m_keys = mockito::mock("GET", "/latest/meta-data/public-keys/") + .with_status(200) + .with_body("0/\ntest/\n") + .create(); +- let _m_key0 = mockito::mock("GET", "/public-keys/0/openssh-key") ++ let _m_key0 = mockito::mock("GET", "/latest/meta-data/public-keys/0/openssh-key") + .with_status(200) + .with_body("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIadOopfaOOAdFWRkCoOimvDyOftqphtnIeiECJuhkdq test-comment") + .create(); +- let _m_keytest = mockito::mock("GET", "/public-keys/test/openssh-key") ++ let _m_keytest = mockito::mock("GET", "/latest/meta-data/public-keys/test/openssh-key") + .with_status(200) + .with_body("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIadOopfaOOAdFWRkCoOimvDyOftqphtnIeiECJuhkdq test-comment") + .create(); +@@ -87,16 +93,16 @@ fn basic_attributes() { + let zone_id = "test-zone-id"; + + let endpoints = maplit::btreemap! { +- "/eipv4" => eipv4, +- "/hostname" => hostname, +- "/image-id" => image_id, +- "/instance-id" => instance_id, +- "/instance/instance-type" => instance_type, +- "/private-ipv4" => private_ipv4, +- "/public-ipv4" => public_ipv4, +- "/region-id" => region_id, +- "/vpc-id" => vpc_id, +- "/zone-id" => zone_id, ++ "/latest/meta-data/eipv4" => eipv4, ++ "/latest/meta-data/hostname" => hostname, ++ "/latest/meta-data/image-id" => image_id, ++ "/latest/meta-data/instance-id" => instance_id, ++ "/latest/meta-data/instance/instance-type" => instance_type, ++ "/latest/meta-data/private-ipv4" => private_ipv4, ++ "/latest/meta-data/public-ipv4" => public_ipv4, ++ "/latest/meta-data/region-id" => region_id, ++ "/latest/meta-data/vpc-id" => vpc_id, ++ "/latest/meta-data/zone-id" => zone_id, + }; + let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints { +@@ -123,7 +129,8 @@ fn basic_attributes() { + let client = crate::retry::Client::try_new() + .unwrap() + .max_retries(0) +- .return_on_404(true); ++ .return_on_404(true) ++ .mock_base_url(mockito::server_url()); + let provider = aliyun::AliyunProvider { client }; + + let v = provider.attributes().unwrap(); +diff --git a/src/providers/aliyun/mod.rs b/src/providers/aliyun/mod.rs +index b4ad0cc21e36..c3c4af19d78d 100644 +--- a/src/providers/aliyun/mod.rs ++++ b/src/providers/aliyun/mod.rs +@@ -4,8 +4,6 @@ + //! The metadata endpoint is documented at https://www.alibabacloud.com/help/doc-detail/49122.htm. + + use anyhow::{anyhow, Result}; +-#[cfg(test)] +-use mockito; + use openssh_keys::PublicKey; + use slog_scope::error; + use std::collections::{BTreeSet, HashMap}; +@@ -31,13 +29,6 @@ impl AliyunProvider { + Ok(AliyunProvider { client }) + } + +- #[cfg(test)] +- fn endpoint_for(name: &str) -> String { +- let url = mockito::server_url(); +- format!("{url}/{name}") +- } +- +- #[cfg(not(test))] + fn endpoint_for(name: &str) -> String { + format!("http://100.100.100.200/latest/meta-data/{}", name) + } +diff --git a/src/providers/aws/mock_tests.rs b/src/providers/aws/mock_tests.rs +index 97bcfc52f810..2542ad9b5845 100644 +--- a/src/providers/aws/mock_tests.rs ++++ b/src/providers/aws/mock_tests.rs +@@ -7,12 +7,13 @@ use mockito; + + #[test] + fn test_aws_basic() { +- let ep = "/meta-data/public-keys"; ++ let ep = "/2021-01-03/meta-data/public-keys"; + let client = crate::retry::Client::try_new() + .context("failed to create http client") + .unwrap() + .max_retries(0) +- .return_on_404(true); ++ .return_on_404(true) ++ .mock_base_url(mockito::server_url()); + let provider = aws::AwsProvider { client }; + + provider.fetch_ssh_keys().unwrap_err(); +@@ -56,16 +57,16 @@ fn aws_get_maps() -> ( + + ( + maplit::btreemap! { +- "/meta-data/instance-id" => instance_id, +- "/meta-data/instance-type" => instance_type, +- "/meta-data/local-ipv4" => ipv4_local, +- "/meta-data/public-ipv4" => ipv4_public, +- "/meta-data/ipv6" => ipv6, +- "/meta-data/placement/availability-zone" => availability_zone, +- "/meta-data/placement/availability-zone-id" => availability_zone_id, +- "/meta-data/hostname" => hostname, +- "/meta-data/public-hostname" => public_hostname, +- "/dynamic/instance-identity/document" => instance_id_doc, ++ "/2021-01-03/meta-data/instance-id" => instance_id, ++ "/2021-01-03/meta-data/instance-type" => instance_type, ++ "/2021-01-03/meta-data/local-ipv4" => ipv4_local, ++ "/2021-01-03/meta-data/public-ipv4" => ipv4_public, ++ "/2021-01-03/meta-data/ipv6" => ipv6, ++ "/2021-01-03/meta-data/placement/availability-zone" => availability_zone, ++ "/2021-01-03/meta-data/placement/availability-zone-id" => availability_zone_id, ++ "/2021-01-03/meta-data/hostname" => hostname, ++ "/2021-01-03/meta-data/public-hostname" => public_hostname, ++ "/2021-01-03/dynamic/instance-identity/document" => instance_id_doc, + }, + maplit::hashmap! { + "AWS_INSTANCE_ID".to_string() => instance_id.to_string(), +@@ -99,7 +100,8 @@ fn test_aws_attributes() { + .context("failed to create http client") + .unwrap() + .max_retries(0) +- .return_on_404(true); ++ .return_on_404(true) ++ .mock_base_url(mockito::server_url()); + let provider = aws::AwsProvider { client }; + + let v = provider.attributes().unwrap(); +@@ -117,7 +119,8 @@ fn test_aws_imds_version1() { + .context("failed to create http client") + .unwrap() + .max_retries(0) +- .return_on_404(true); ++ .return_on_404(true) ++ .mock_base_url(mockito::server_url()); + + let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints.clone() { +@@ -128,7 +131,7 @@ fn test_aws_imds_version1() { + mocks.push(m); + } + +- let _m = mockito::mock("PUT", "/api/token") ++ let _m = mockito::mock("PUT", "/latest/api/token") + .match_header("X-aws-ec2-metadata-token-ttl-seconds", "21600") + .with_status(403) + .with_body("Forbidden") +@@ -152,7 +155,8 @@ fn test_aws_imds_version2() { + .context("failed to create http client") + .unwrap() + .max_retries(0) +- .return_on_404(true); ++ .return_on_404(true) ++ .mock_base_url(mockito::server_url()); + + let token = "test-api-token"; + let mut mocks = Vec::with_capacity(endpoints.len()); +@@ -165,7 +169,7 @@ fn test_aws_imds_version2() { + mocks.push(m); + } + +- let _m = mockito::mock("PUT", "/api/token") ++ let _m = mockito::mock("PUT", "/latest/api/token") + .match_header("X-aws-ec2-metadata-token-ttl-seconds", "21600") + .with_status(200) + .with_body(token) +diff --git a/src/providers/aws/mod.rs b/src/providers/aws/mod.rs +index 8a6cce50182d..af81227c8105 100644 +--- a/src/providers/aws/mod.rs ++++ b/src/providers/aws/mod.rs +@@ -18,8 +18,6 @@ + use std::collections::HashMap; + + use anyhow::{anyhow, bail, Context, Result}; +-#[cfg(test)] +-use mockito; + use openssh_keys::PublicKey; + use reqwest::header; + use serde::Deserialize; +@@ -71,13 +69,6 @@ impl AwsProvider { + Ok(AwsProvider { client }) + } + +- #[cfg(test)] +- fn endpoint_for(key: &str, _use_latest: bool) -> String { +- let url = mockito::server_url(); +- format!("{url}/{key}") +- } +- +- #[cfg(not(test))] + fn endpoint_for(key: &str, use_latest: bool) -> String { + // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html + const URL: &str = "http://169.254.169.254/2021-01-03"; +diff --git a/src/providers/cloudstack/mock_tests.rs b/src/providers/cloudstack/mock_tests.rs +index 4732c8755cdc..d1b4456527dc 100644 +--- a/src/providers/cloudstack/mock_tests.rs ++++ b/src/providers/cloudstack/mock_tests.rs +@@ -4,7 +4,10 @@ use crate::providers::MetadataProvider; + #[test] + fn test_ssh_keys() { + let mut provider = CloudstackNetwork::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + + let key1 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsXe6CfHl45kCIzMF92VhDf2NpBWUyS1+IiTtxm5a83mT9730Hb8xim7GYeJu47kiESw2DAN8vNJ/Irg0apZ217ah2rXXjPQuWYSXuEuap8yLBSjqw8exgqVj/kzW+YqmnHASxI13eoFDxTQQGzyqbqowvxu/5gQmDwBmNAa9bT809ziB/qmpS1mD6qyyFDpR23kUwu3TkgAbwMXBDoqK+pdwfaF9uo9XaLHNEH8lD5BZuG2BeDafm2o76DhNSo83MvcCPNXKLxu3BbX/FCMFO6O8RRqony4i91fEV1b8TbXrbJz1bwEYEnJRvmjnqI/389tQFeYvplXR2WdT9PCKyEAG+j8y6XgecIcdTqV/7gFfak1mp2S7mYHZDnXixsn3MjCP/cIxxJVDitKusnj1TdFqtSXl4tqGccbg/5Sqnt/EVSK4bGwwBxv/YmE0P9cbXLxuEVI0JYzgrQvC8TtUgd8kUu2jqi1/Yj9IWm3aFsl/hhh8YwYrv/gm8PV0TxkM= root@example1"; + let key2 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDj6FBVgkTt7/DB93VVLk6304Nx7WUjLBJDSCh38zjCimHUpeo9uYDxflfu2N1CLtrSImIKBVP/JRy9g7K4zmRAH/wXw2UxYziX+hZoFIpbW3GmYQqhjx2lDvIRXJI7blhHhTUNWX5f10lFAYOLqA9J859AB1w7ND09+MS3jQgSazCx17h+QZ0qQ6kLSfnXw9PMUOE1Xba9hD1nYj14ryTVj9jrFPMFuUfXdb/G9lsDJ+cGvdE2/RMuPfDmEdo04zvZ5fQJJKvS7OyAuYev4Y+JC8MhEr756ITDZ17yq4BEMo/8rNPxZ5Von/8xnvry+8/2C3ep9rZyHtCwpRb6WT6TndV2ddXKhEIneyd1XiOcWPJguHj5vSoMN3mo8k2PvznGauvxBstvpjUSFLQu869/ZQwyMnbQi3wnkJk5CpLXePXn1J9njocJjt8+SKGijmmIAsmYosx8gmmu3H1mvq9Wi0qqWDITMm+J24AZBEPBhwVrjhLZb5MKxylF6JFJJBs= root@example2"; +@@ -29,7 +32,10 @@ fn test_ssh_keys() { + #[test] + fn test_ssh_keys_404_ok() { + let mut provider = CloudstackNetwork::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + + let _m = mockito::mock("GET", "/latest/meta-data/public-keys") + .with_status(404) +diff --git a/src/providers/cloudstack/network.rs b/src/providers/cloudstack/network.rs +index 11e4ca0ecaf8..74d4a53f5dfa 100644 +--- a/src/providers/cloudstack/network.rs ++++ b/src/providers/cloudstack/network.rs +@@ -33,8 +33,8 @@ impl CloudstackNetwork { + + fn get_server_base_url_from_dhcp() -> Result { + if cfg!(test) { +- #[cfg(test)] +- return Ok(mockito::server_url()); ++ // will be ignored by retry.Client ++ return Ok("http://localhost".into()); + } + let server = DhcpOption::DhcpServerId.get_value()?; + let ip = server +diff --git a/src/providers/exoscale/mock_tests.rs b/src/providers/exoscale/mock_tests.rs +index a0fe22074de3..b0d80fdc930c 100644 +--- a/src/providers/exoscale/mock_tests.rs ++++ b/src/providers/exoscale/mock_tests.rs +@@ -4,11 +4,14 @@ use mockito; + + #[test] + fn basic_hostname() { +- let ep = "/local-hostname"; ++ let ep = "/1.0/meta-data/local-hostname"; + let hostname = "test-hostname"; + + let mut provider = exoscale::ExoscaleProvider::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + + { + let _m503 = mockito::mock("GET", ep).with_status(503).create(); +@@ -40,9 +43,12 @@ fn basic_hostname() { + #[test] + fn basic_pubkeys() { + let mut provider = exoscale::ExoscaleProvider::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + +- let _m_keys = mockito::mock("GET", "/public-keys") ++ let _m_keys = mockito::mock("GET", "/1.0/meta-data/public-keys") + .with_status(200) + .with_body("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+bqdi18/+JfjrqmOEtVKyCU0bsIc6tBqqU7p9mesJkALocLddDU6d97w2zwERhzaqReDyg4msvQQohgtncb4afKKWQjCCCWlcwtP0nAeg9GFtUfmLeYcP2KAjxblabncluuAnvMHyBixKAjr5eWD4B1HjOmpMRmycwmy85QhGTYhF+AkiHGCPPUDrVy2cIvrPSDXEEa7bz5aQUime0Eold56n3O7E5BJuAozf+oeiWCERRRt9ATlLkMvwVItzBHN25YoMOd0KfgYMtBVAw86TErYFx4Tu98blYNUQTthf9VxcU8xy0rFacXmuS7LHbp+CKDY0X5dNHuhqz0wFto4J test-comment") + .create(); +@@ -71,15 +77,15 @@ fn basic_attributes() { + let vm_id = "test-vm-id"; + + let endpoints = maplit::btreemap! { +- "/local-hostname" => local_hostname, +- "/public-hostname" => public_hostname, +- "/instance-id" => instance_id, +- "/service-offering" => service_offering, +- "/local-ipv4" => local_ipv4, +- "/public-ipv4" => public_ipv4, +- "/availability-zone" => availability_zone, +- "/cloud-identifier" => cloud_identifier, +- "/vm-id" => vm_id, ++ "/1.0/meta-data/local-hostname" => local_hostname, ++ "/1.0/meta-data/public-hostname" => public_hostname, ++ "/1.0/meta-data/instance-id" => instance_id, ++ "/1.0/meta-data/service-offering" => service_offering, ++ "/1.0/meta-data/local-ipv4" => local_ipv4, ++ "/1.0/meta-data/public-ipv4" => public_ipv4, ++ "/1.0/meta-data/availability-zone" => availability_zone, ++ "/1.0/meta-data/cloud-identifier" => cloud_identifier, ++ "/1.0/meta-data/vm-id" => vm_id, + }; + let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints { +@@ -105,7 +111,8 @@ fn basic_attributes() { + let client = crate::retry::Client::try_new() + .unwrap() + .max_retries(0) +- .return_on_404(true); ++ .return_on_404(true) ++ .mock_base_url(mockito::server_url()); + let provider = exoscale::ExoscaleProvider { client }; + + let v = provider.attributes().unwrap(); +diff --git a/src/providers/exoscale/mod.rs b/src/providers/exoscale/mod.rs +index ac0b65970d1a..b3e7fdaebfe4 100644 +--- a/src/providers/exoscale/mod.rs ++++ b/src/providers/exoscale/mod.rs +@@ -39,13 +39,6 @@ impl ExoscaleProvider { + Ok(ExoscaleProvider { client }) + } + +- #[cfg(test)] +- fn endpoint_for(&self, key: &str) -> String { +- let url = mockito::server_url(); +- format!("{url}/{key}") +- } +- +- #[cfg(not(test))] + fn endpoint_for(&self, key: &str) -> String { + format!("http://169.254.169.254/1.0/meta-data/{key}") + } +diff --git a/src/providers/gcp/mock_tests.rs b/src/providers/gcp/mock_tests.rs +index d70897b9f355..4cfadab7b632 100644 +--- a/src/providers/gcp/mock_tests.rs ++++ b/src/providers/gcp/mock_tests.rs +@@ -4,11 +4,14 @@ use mockito; + + #[test] + fn basic_hostname() { +- let ep = "/instance/hostname"; ++ let ep = "/computeMetadata/v1/instance/hostname"; + let hostname = "test-hostname"; + + let mut provider = gcp::GcpProvider::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + + { + let _m503 = mockito::mock("GET", ep).with_status(503).create(); +@@ -42,10 +45,10 @@ fn basic_attributes() { + let machine_type = "test-machine-type"; + + let endpoints = maplit::btreemap! { +- "/instance/hostname" => hostname, +- "/instance/network-interfaces/0/access-configs/0/external-ip" => ip_external, +- "/instance/network-interfaces/0/ip" => ip_local, +- "/instance/machine-type" => machine_type, ++ "/computeMetadata/v1/instance/hostname" => hostname, ++ "/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" => ip_external, ++ "/computeMetadata/v1/instance/network-interfaces/0/ip" => ip_local, ++ "/computeMetadata/v1/instance/machine-type" => machine_type, + }; + let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints { +@@ -66,7 +69,8 @@ fn basic_attributes() { + let client = crate::retry::Client::try_new() + .unwrap() + .max_retries(0) +- .return_on_404(true); ++ .return_on_404(true) ++ .mock_base_url(mockito::server_url()); + let provider = gcp::GcpProvider { client }; + + let v = provider.attributes().unwrap(); +diff --git a/src/providers/gcp/mod.rs b/src/providers/gcp/mod.rs +index 7f2f09d2797b..344b1a6b8888 100644 +--- a/src/providers/gcp/mod.rs ++++ b/src/providers/gcp/mod.rs +@@ -15,8 +15,6 @@ + //! google compute engine metadata fetcher + + use anyhow::{anyhow, Result}; +-#[cfg(test)] +-use mockito; + use openssh_keys::PublicKey; + use reqwest::header::{HeaderName, HeaderValue}; + use std::collections::HashMap; +@@ -46,13 +44,6 @@ impl GcpProvider { + Ok(GcpProvider { client }) + } + +- #[cfg(test)] +- fn endpoint_for(name: &str) -> String { +- let url = mockito::server_url(); +- format!("{url}/{name}") +- } +- +- #[cfg(not(test))] + fn endpoint_for(name: &str) -> String { + format!("http://169.254.169.254/computeMetadata/v1/{name}") + } +diff --git a/src/providers/microsoft/azure/mock_tests.rs b/src/providers/microsoft/azure/mock_tests.rs +index 476555dc6368..ebe1526cca7c 100644 +--- a/src/providers/microsoft/azure/mock_tests.rs ++++ b/src/providers/microsoft/azure/mock_tests.rs +@@ -125,8 +125,11 @@ fn test_boot_checkin() { + .with_status(200) + .create(); + +- let provider = azure::Azure::try_new(); +- let r = provider.unwrap().boot_checkin(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azure::Azure::with_client(Some(client)).unwrap(); ++ let r = provider.boot_checkin(); + + m_version.assert(); + m_goalstate.assert(); +@@ -136,7 +139,10 @@ fn test_boot_checkin() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + +@@ -152,8 +158,11 @@ fn test_hostname() { + .with_status(200) + .create(); + +- let provider = azure::Azure::try_new(); +- let r = provider.unwrap().hostname().unwrap(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azure::Azure::with_client(Some(client)).unwrap(); ++ let r = provider.hostname().unwrap(); + + m_version.assert(); + +@@ -164,7 +173,10 @@ fn test_hostname() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + +@@ -180,8 +192,11 @@ fn test_vmsize() { + .with_status(200) + .create(); + +- let provider = azure::Azure::try_new(); +- let attributes = provider.unwrap().attributes().unwrap(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azure::Azure::with_client(Some(client)).unwrap(); ++ let attributes = provider.attributes().unwrap(); + let r = attributes.get("AZURE_VMSIZE"); + + m_version.assert(); +@@ -193,7 +208,10 @@ fn test_vmsize() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = retry::Client::try_new().unwrap().max_retries(0); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + +@@ -202,7 +220,10 @@ fn test_goalstate_certs() { + let m_version = mock_fab_version(); + let m_goalstate = mock_goalstate(true); + +- let provider = azure::Azure::try_new().unwrap(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azure::Azure::with_client(Some(client)).unwrap(); + let goalstate = provider.fetch_goalstate().unwrap(); + + m_version.assert(); +@@ -220,7 +241,10 @@ fn test_goalstate_no_certs() { + let m_version = mock_fab_version(); + let m_goalstate = mock_goalstate(false); + +- let provider = azure::Azure::try_new().unwrap(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azure::Azure::with_client(Some(client)).unwrap(); + let goalstate = provider.fetch_goalstate().unwrap(); + + m_version.assert(); +diff --git a/src/providers/microsoft/azure/mod.rs b/src/providers/microsoft/azure/mod.rs +index 1d2803c797c3..83cdac8aab1a 100644 +--- a/src/providers/microsoft/azure/mod.rs ++++ b/src/providers/microsoft/azure/mod.rs +@@ -189,7 +189,6 @@ impl Azure { + Ok(IpAddr::V4(dec.into())) + } + +- #[cfg(not(test))] + fn fabric_base_url(&self) -> String { + format!("http://{}", self.endpoint) + } +@@ -200,11 +199,6 @@ impl Azure { + IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)) + } + +- #[cfg(test)] +- fn fabric_base_url(&self) -> String { +- mockito::server_url().to_string() +- } +- + fn is_fabric_compatible(&self, version: &str) -> Result<()> { + let versions: Versions = self + .client +@@ -227,15 +221,8 @@ impl Azure { + } + } + +- #[cfg(test)] +- fn metadata_endpoint() -> String { +- mockito::server_url() +- } +- +- #[cfg(not(test))] + fn metadata_endpoint() -> String { +- const URL: &str = "http://169.254.169.254"; +- URL.to_string() ++ "http://169.254.169.254".into() + } + + // Fetch the certificate. +diff --git a/src/providers/microsoft/azurestack/mock_tests.rs b/src/providers/microsoft/azurestack/mock_tests.rs +index 655908237337..83141dcec330 100644 +--- a/src/providers/microsoft/azurestack/mock_tests.rs ++++ b/src/providers/microsoft/azurestack/mock_tests.rs +@@ -125,8 +125,11 @@ fn test_boot_checkin() { + .with_status(200) + .create(); + +- let provider = azurestack::AzureStack::try_new(); +- let r = provider.unwrap().boot_checkin(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); ++ let r = provider.boot_checkin(); + + m_version.assert(); + m_goalstate.assert(); +@@ -153,8 +156,11 @@ fn test_identity() { + .with_status(200) + .create(); + +- let provider = azurestack::AzureStack::try_new(); +- let r = provider.unwrap().hostname().unwrap(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); ++ let r = provider.hostname().unwrap(); + + m_version.assert(); + +@@ -182,8 +188,11 @@ fn test_hostname() { + .with_status(200) + .create(); + +- let provider = azurestack::AzureStack::try_new(); +- let r = provider.unwrap().hostname().unwrap(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); ++ let r = provider.hostname().unwrap(); + + m_version.assert(); + +@@ -203,7 +212,10 @@ fn test_goalstate_certs() { + let m_version = mock_fab_version(); + let m_goalstate = mock_goalstate(true); + +- let provider = azurestack::AzureStack::try_new().unwrap(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); + let goalstate = provider.fetch_goalstate().unwrap(); + + m_version.assert(); +@@ -221,7 +233,10 @@ fn test_goalstate_no_certs() { + let m_version = mock_fab_version(); + let m_goalstate = mock_goalstate(false); + +- let provider = azurestack::AzureStack::try_new().unwrap(); ++ let client = retry::Client::try_new() ++ .unwrap() ++ .mock_base_url(mockito::server_url()); ++ let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); + let goalstate = provider.fetch_goalstate().unwrap(); + + m_version.assert(); +diff --git a/src/providers/microsoft/azurestack/mod.rs b/src/providers/microsoft/azurestack/mod.rs +index 04974398ee40..045705a756f6 100644 +--- a/src/providers/microsoft/azurestack/mod.rs ++++ b/src/providers/microsoft/azurestack/mod.rs +@@ -205,7 +205,6 @@ impl AzureStack { + Ok(IpAddr::V4(dec.into())) + } + +- #[cfg(not(test))] + fn fabric_base_url(&self) -> String { + format!("http://{}", self.endpoint) + } +@@ -216,11 +215,6 @@ impl AzureStack { + IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)) + } + +- #[cfg(test)] +- fn fabric_base_url(&self) -> String { +- mockito::server_url().to_string() +- } +- + fn is_fabric_compatible(&self, version: &str) -> Result<()> { + let versions: Versions = self + .client +@@ -243,15 +237,8 @@ impl AzureStack { + } + } + +- #[cfg(test)] +- fn metadata_endpoint() -> String { +- mockito::server_url() +- } +- +- #[cfg(not(test))] + fn metadata_endpoint() -> String { +- const URL: &str = "http://169.254.169.254"; +- URL.to_string() ++ "http://169.254.169.254".into() + } + + // Fetch the certificate. +diff --git a/src/providers/openstack/mock_tests.rs b/src/providers/openstack/mock_tests.rs +index 334abc7d1552..d1d47e62bd88 100644 +--- a/src/providers/openstack/mock_tests.rs ++++ b/src/providers/openstack/mock_tests.rs +@@ -5,14 +5,17 @@ use mockito; + #[test] + fn test_ssh_keys() { + let mut provider = OpenstackProviderNetwork::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + + let key1 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsXe6CfHl45kCIzMF92VhDf2NpBWUyS1+IiTtxm5a83mT9730Hb8xim7GYeJu47kiESw2DAN8vNJ/Irg0apZ217ah2rXXjPQuWYSXuEuap8yLBSjqw8exgqVj/kzW+YqmnHASxI13eoFDxTQQGzyqbqowvxu/5gQmDwBmNAa9bT809ziB/qmpS1mD6qyyFDpR23kUwu3TkgAbwMXBDoqK+pdwfaF9uo9XaLHNEH8lD5BZuG2BeDafm2o76DhNSo83MvcCPNXKLxu3BbX/FCMFO6O8RRqony4i91fEV1b8TbXrbJz1bwEYEnJRvmjnqI/389tQFeYvplXR2WdT9PCKyEAG+j8y6XgecIcdTqV/7gFfak1mp2S7mYHZDnXixsn3MjCP/cIxxJVDitKusnj1TdFqtSXl4tqGccbg/5Sqnt/EVSK4bGwwBxv/YmE0P9cbXLxuEVI0JYzgrQvC8TtUgd8kUu2jqi1/Yj9IWm3aFsl/hhh8YwYrv/gm8PV0TxkM= root@example1"; + let key2 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDj6FBVgkTt7/DB93VVLk6304Nx7WUjLBJDSCh38zjCimHUpeo9uYDxflfu2N1CLtrSImIKBVP/JRy9g7K4zmRAH/wXw2UxYziX+hZoFIpbW3GmYQqhjx2lDvIRXJI7blhHhTUNWX5f10lFAYOLqA9J859AB1w7ND09+MS3jQgSazCx17h+QZ0qQ6kLSfnXw9PMUOE1Xba9hD1nYj14ryTVj9jrFPMFuUfXdb/G9lsDJ+cGvdE2/RMuPfDmEdo04zvZ5fQJJKvS7OyAuYev4Y+JC8MhEr756ITDZ17yq4BEMo/8rNPxZ5Von/8xnvry+8/2C3ep9rZyHtCwpRb6WT6TndV2ddXKhEIneyd1XiOcWPJguHj5vSoMN3mo8k2PvznGauvxBstvpjUSFLQu869/ZQwyMnbQi3wnkJk5CpLXePXn1J9njocJjt8+SKGijmmIAsmYosx8gmmu3H1mvq9Wi0qqWDITMm+J24AZBEPBhwVrjhLZb5MKxylF6JFJJBs= root@example2"; + let endpoints = maplit::btreemap! { +- "/public-keys" => "0=test1\n1=test2", +- "/public-keys/0/openssh-key" => key1, +- "/public-keys/1/openssh-key" => key2, ++ "/latest/meta-data/public-keys" => "0=test1\n1=test2", ++ "/latest/meta-data/public-keys/0/openssh-key" => key1, ++ "/latest/meta-data/public-keys/1/openssh-key" => key2, + }; + + let mut mocks = Vec::with_capacity(endpoints.len()); +@@ -39,9 +42,12 @@ fn test_ssh_keys() { + #[test] + fn test_ssh_keys_404_ok() { + let mut provider = OpenstackProviderNetwork::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + +- let _m = mockito::mock("GET", "/public-keys") ++ let _m = mockito::mock("GET", "/latest/meta-data/public-keys") + .with_status(404) + .create(); + let v = provider.ssh_keys().unwrap(); +diff --git a/src/providers/openstack/network.rs b/src/providers/openstack/network.rs +index 560271eb0411..b263e1283331 100644 +--- a/src/providers/openstack/network.rs ++++ b/src/providers/openstack/network.rs +@@ -8,7 +8,6 @@ use openssh_keys::PublicKey; + use crate::providers::MetadataProvider; + use crate::retry; + +-#[cfg(not(test))] + const URL: &str = "http://169.254.169.254/latest/meta-data"; + + #[derive(Clone, Debug)] +@@ -22,12 +21,6 @@ impl OpenstackProviderNetwork { + Ok(OpenstackProviderNetwork { client }) + } + +- #[cfg(test)] +- fn endpoint_for(key: &str) -> String { +- format!("{}/{}", &mockito::server_url(), key) +- } +- +- #[cfg(not(test))] + fn endpoint_for(key: &str) -> String { + format!("{}/{}", URL, key) + } +diff --git a/src/providers/packet/mock_tests.rs b/src/providers/packet/mock_tests.rs +index ef26be4c7759..c2027a77c468 100644 +--- a/src/providers/packet/mock_tests.rs ++++ b/src/providers/packet/mock_tests.rs +@@ -3,7 +3,10 @@ use mockito::{self, Matcher}; + + #[test] + fn test_boot_checkin() { +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); ++ let client = crate::retry::Client::try_new() ++ .unwrap() ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + let data = packet::PacketData { + id: String::new(), + hostname: String::new(), +@@ -118,7 +121,11 @@ fn test_packet_attributes() { + .with_body(metadata) + .create(); + +- let provider = packet::PacketProvider::try_new().unwrap(); ++ let client = crate::retry::Client::try_new() ++ .unwrap() ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); ++ let provider = packet::PacketProvider::fetch_content(Some(client)).unwrap(); + let v = provider.attributes().unwrap(); + + assert_eq!(v, attributes); +@@ -126,6 +133,9 @@ fn test_packet_attributes() { + mockito::reset(); + + // Check error logic, but fail fast without re-trying. +- let client = crate::retry::Client::try_new().unwrap().max_retries(0); ++ let client = crate::retry::Client::try_new() ++ .unwrap() ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + packet::PacketProvider::fetch_content(Some(client)).unwrap_err(); + } +diff --git a/src/providers/packet/mod.rs b/src/providers/packet/mod.rs +index 98a4018581b4..b871efb46410 100644 +--- a/src/providers/packet/mod.rs ++++ b/src/providers/packet/mod.rs +@@ -117,16 +117,8 @@ impl PacketProvider { + Ok(Self { client, data }) + } + +- #[cfg(test)] + fn endpoint_for(name: &str) -> String { +- let url = mockito::server_url(); +- format!("{url}/{name}") +- } +- +- #[cfg(not(test))] +- fn endpoint_for(name: &str) -> String { +- let url = "https://metadata.packet.net"; +- format!("{url}/{name}") ++ format!("https://metadata.packet.net/{name}") + } + + fn get_attrs(&self) -> Vec<(String, String)> { +diff --git a/src/providers/vultr/mock_tests.rs b/src/providers/vultr/mock_tests.rs +index 418e4288aa36..34878e869224 100644 +--- a/src/providers/vultr/mock_tests.rs ++++ b/src/providers/vultr/mock_tests.rs +@@ -4,11 +4,14 @@ use mockito; + + #[test] + fn test_hostname() { +- let ep = "/hostname"; ++ let ep = "/v1/hostname"; + let hostname = "test-hostname"; + + let mut provider = vultr::VultrProvider::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + + { + let _m503 = mockito::mock("GET", ep).with_status(503).create(); +@@ -46,9 +49,12 @@ fn test_hostname() { + #[test] + fn test_pubkeys() { + let mut provider = vultr::VultrProvider::try_new().unwrap(); +- provider.client = provider.client.max_retries(0); ++ provider.client = provider ++ .client ++ .max_retries(0) ++ .mock_base_url(mockito::server_url()); + +- let _m_keys = mockito::mock("GET", "/public-keys") ++ let _m_keys = mockito::mock("GET", "/v1/public-keys") + .with_status(200) + .with_body("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsXe6CfHl45kCIzMF92VhDf2NpBWUyS1+IiTtxm5a83mT9730Hb8xim7GYeJu47kiESw2DAN8vNJ/Irg0apZ217ah2rXXjPQuWYSXuEuap8yLBSjqw8exgqVj/kzW+YqmnHASxI13eoFDxTQQGzyqbqowvxu/5gQmDwBmNAa9bT809ziB/qmpS1mD6qyyFDpR23kUwu3TkgAbwMXBDoqK+pdwfaF9uo9XaLHNEH8lD5BZuG2BeDafm2o76DhNSo83MvcCPNXKLxu3BbX/FCMFO6O8RRqony4i91fEV1b8TbXrbJz1bwEYEnJRvmjnqI/389tQFeYvplXR2WdT9PCKyEAG+j8y6XgecIcdTqV/7gFfak1mp2S7mYHZDnXixsn3MjCP/cIxxJVDitKusnj1TdFqtSXl4tqGccbg/5Sqnt/EVSK4bGwwBxv/YmE0P9cbXLxuEVI0JYzgrQvC8TtUgd8kUu2jqi1/Yj9IWm3aFsl/hhh8YwYrv/gm8PV0TxkM= root@example1\n + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDj6FBVgkTt7/DB93VVLk6304Nx7WUjLBJDSCh38zjCimHUpeo9uYDxflfu2N1CLtrSImIKBVP/JRy9g7K4zmRAH/wXw2UxYziX+hZoFIpbW3GmYQqhjx2lDvIRXJI7blhHhTUNWX5f10lFAYOLqA9J859AB1w7ND09+MS3jQgSazCx17h+QZ0qQ6kLSfnXw9PMUOE1Xba9hD1nYj14ryTVj9jrFPMFuUfXdb/G9lsDJ+cGvdE2/RMuPfDmEdo04zvZ5fQJJKvS7OyAuYev4Y+JC8MhEr756ITDZ17yq4BEMo/8rNPxZ5Von/8xnvry+8/2C3ep9rZyHtCwpRb6WT6TndV2ddXKhEIneyd1XiOcWPJguHj5vSoMN3mo8k2PvznGauvxBstvpjUSFLQu869/ZQwyMnbQi3wnkJk5CpLXePXn1J9njocJjt8+SKGijmmIAsmYosx8gmmu3H1mvq9Wi0qqWDITMm+J24AZBEPBhwVrjhLZb5MKxylF6JFJJBs= root@example2") +@@ -75,9 +81,9 @@ fn test_attributes() { + let regioncode = "test-regioncode"; + + let endpoints = maplit::btreemap! { +- "/hostname" => hostname, +- "/instanceid" => instance_id, +- "/region/regioncode" => regioncode, ++ "/v1/hostname" => hostname, ++ "/v1/instanceid" => instance_id, ++ "/v1/region/regioncode" => regioncode, + }; + + let mut mocks = Vec::with_capacity(endpoints.len()); +@@ -98,7 +104,8 @@ fn test_attributes() { + let client = crate::retry::Client::try_new() + .unwrap() + .max_retries(0) +- .return_on_404(true); ++ .return_on_404(true) ++ .mock_base_url(mockito::server_url()); + let provider = vultr::VultrProvider { client }; + + let v = provider.attributes().unwrap(); +diff --git a/src/providers/vultr/mod.rs b/src/providers/vultr/mod.rs +index e2339e2b4d9b..5ed867d40b8c 100644 +--- a/src/providers/vultr/mod.rs ++++ b/src/providers/vultr/mod.rs +@@ -17,8 +17,6 @@ + //! The metadata endpoint is documented at https://www.vultr.com/metadata/. + + use anyhow::Result; +-#[cfg(test)] +-use mockito; + use openssh_keys::PublicKey; + use slog_scope::error; + use std::collections::HashMap; +@@ -41,13 +39,6 @@ impl VultrProvider { + Ok(VultrProvider { client }) + } + +- #[cfg(test)] +- fn endpoint_for(name: &str) -> String { +- let url = mockito::server_url(); +- format!("{url}/{name}") +- } +- +- #[cfg(not(test))] + fn endpoint_for(name: &str) -> String { + format!("http://169.254.169.254/v1/{}", name) + } +diff --git a/src/retry/client.rs b/src/retry/client.rs +index e113fe4bc69a..954ed710c888 100644 +--- a/src/retry/client.rs ++++ b/src/retry/client.rs +@@ -94,6 +94,8 @@ pub struct Client { + headers: header::HeaderMap, + retry: Retry, + return_on_404: bool, ++ #[cfg(test)] ++ mock_base_url: Option, + } + + impl Client { +@@ -106,6 +108,8 @@ impl Client { + headers: header::HeaderMap::new(), + retry: Retry::new(), + return_on_404: false, ++ #[cfg(test)] ++ mock_base_url: None, + }) + } + +@@ -141,6 +145,12 @@ impl Client { + self + } + ++ #[cfg(test)] ++ pub fn mock_base_url(mut self, base_url: String) -> Self { ++ self.mock_base_url = Some(base_url); ++ self ++ } ++ + pub fn get(&self, d: D, url: String) -> RequestBuilder + where + D: Deserializer, +@@ -153,6 +163,8 @@ impl Client { + headers: self.headers.clone(), + retry: self.retry.clone(), + return_on_404: self.return_on_404, ++ #[cfg(test)] ++ mock_base_url: self.mock_base_url.clone(), + } + } + +@@ -168,6 +180,8 @@ impl Client { + headers: self.headers.clone(), + retry: self.retry.clone(), + return_on_404: self.return_on_404, ++ #[cfg(test)] ++ mock_base_url: self.mock_base_url.clone(), + } + } + +@@ -183,6 +197,8 @@ impl Client { + headers: self.headers.clone(), + retry: self.retry.clone(), + return_on_404: self.return_on_404, ++ #[cfg(test)] ++ mock_base_url: self.mock_base_url.clone(), + } + } + } +@@ -198,6 +214,8 @@ where + headers: header::HeaderMap, + retry: Retry, + return_on_404: bool, ++ #[cfg(test)] ++ mock_base_url: Option, + } + + impl RequestBuilder +@@ -310,7 +328,24 @@ where + } + + fn parse_url(&self) -> Result { +- reqwest::Url::parse(self.url.as_str()).context("failed to parse uri") ++ #[allow(unused_mut)] ++ let mut url = reqwest::Url::parse(self.url.as_str()).context("failed to parse uri")?; ++ #[cfg(test)] ++ if let Some(mock_base_url) = &self.mock_base_url { ++ let base_url = ++ reqwest::Url::parse(mock_base_url).context("failed to parse mock base URL")?; ++ url.set_scheme(base_url.scheme()) ++ .map_err(|_| anyhow!("failed to update URL scheme"))?; ++ let host = base_url ++ .host() ++ .context("mock base URL doesn't have a host")? ++ .to_string(); ++ url.set_host(Some(&host)) ++ .context("failed to update URL host")?; ++ url.set_port(base_url.port()) ++ .map_err(|_| anyhow!("failed to update URL port"))?; ++ } ++ Ok(url) + } + } + +-- +2.39.2 + diff --git a/0006-Update-mockito-to-1.0.patch b/0006-Update-mockito-to-1.0.patch new file mode 100644 index 0000000..262b678 --- /dev/null +++ b/0006-Update-mockito-to-1.0.patch @@ -0,0 +1,1246 @@ +From f6b35f101b92eef01363431e0756e3b6b4c9813e Mon Sep 17 00:00:00 2001 +From: Benjamin Gilbert +Date: Mon, 20 Mar 2023 02:56:09 -0400 +Subject: [PATCH 6/6] Update mockito to 1.0 + +The global server object has been removed, so we need to explicitly create +servers and configure mocks on them. + +Individual mocks are no longer removed from servers when they go out of +scope. Stop artificially keeping mocks in scope. +--- + src/providers/aliyun/mock_tests.rs | 77 ++++++++----------- + src/providers/aws/mock_tests.rs | 65 ++++++++-------- + src/providers/cloudstack/mock_tests.rs | 22 +++--- + src/providers/exoscale/mock_tests.rs | 64 +++++++-------- + src/providers/gcp/mock_tests.rs | 47 +++++------ + src/providers/microsoft/azure/mock_tests.rs | 66 +++++++++------- + .../microsoft/azurestack/mock_tests.rs | 60 +++++++++------ + src/providers/openstack/mock_tests.rs | 24 +++--- + src/providers/packet/mock_tests.rs | 20 +++-- + src/providers/vultr/mock_tests.rs | 72 ++++++++--------- + 10 files changed, 248 insertions(+), 269 deletions(-) + +diff --git a/src/providers/aliyun/mock_tests.rs b/src/providers/aliyun/mock_tests.rs +index 55c795bb2592..c8b89baffb3c 100644 +--- a/src/providers/aliyun/mock_tests.rs ++++ b/src/providers/aliyun/mock_tests.rs +@@ -7,63 +7,54 @@ fn basic_hostname() { + let ep = "/latest/meta-data/hostname"; + let hostname = "test-hostname"; + ++ let mut server = mockito::Server::new(); + let mut provider = aliyun::AliyunProvider::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + +- { +- let _m503 = mockito::mock("GET", ep).with_status(503).create(); +- provider.hostname().unwrap_err(); +- } ++ server.mock("GET", ep).with_status(503).create(); ++ provider.hostname().unwrap_err(); + +- { +- let _m200 = mockito::mock("GET", ep) +- .with_status(200) +- .with_body(hostname) +- .create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, Some(hostname.to_string())); +- } ++ server ++ .mock("GET", ep) ++ .with_status(200) ++ .with_body(hostname) ++ .create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, Some(hostname.to_string())); + +- { +- let _m404 = mockito::mock("GET", ep).with_status(404).create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, None); +- } ++ server.mock("GET", ep).with_status(404).create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, None); + +- { +- let _m200_empty = mockito::mock("GET", ep) +- .with_status(200) +- .with_body("") +- .create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, None); +- } ++ server ++ .mock("GET", ep) ++ .with_status(200) ++ .with_body("") ++ .create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, None); + +- mockito::reset(); ++ server.reset(); + provider.hostname().unwrap_err(); + } + + #[test] + fn basic_pubkeys() { ++ let mut server = mockito::Server::new(); + let mut provider = aliyun::AliyunProvider::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + + // Setup two entries with identical content, in order to test de-dup. +- let _m_keys = mockito::mock("GET", "/latest/meta-data/public-keys/") ++ server ++ .mock("GET", "/latest/meta-data/public-keys/") + .with_status(200) + .with_body("0/\ntest/\n") + .create(); +- let _m_key0 = mockito::mock("GET", "/latest/meta-data/public-keys/0/openssh-key") ++ server.mock("GET", "/latest/meta-data/public-keys/0/openssh-key") + .with_status(200) + .with_body("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIadOopfaOOAdFWRkCoOimvDyOftqphtnIeiECJuhkdq test-comment") + .create(); +- let _m_keytest = mockito::mock("GET", "/latest/meta-data/public-keys/test/openssh-key") ++ server.mock("GET", "/latest/meta-data/public-keys/test/openssh-key") + .with_status(200) + .with_body("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIadOopfaOOAdFWRkCoOimvDyOftqphtnIeiECJuhkdq test-comment") + .create(); +@@ -75,7 +66,7 @@ fn basic_pubkeys() { + assert_eq!(keys[0].options, None); + assert_eq!(keys[0].comment, Some("test-comment".to_string())); + +- mockito::reset(); ++ server.reset(); + provider.ssh_keys().unwrap_err(); + } + +@@ -104,13 +95,13 @@ fn basic_attributes() { + "/latest/meta-data/vpc-id" => vpc_id, + "/latest/meta-data/zone-id" => zone_id, + }; +- let mut mocks = Vec::with_capacity(endpoints.len()); ++ let mut server = mockito::Server::new(); + for (endpoint, body) in endpoints { +- let m = mockito::mock("GET", endpoint) ++ server ++ .mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); +- mocks.push(m); + } + + let attributes = maplit::hashmap! { +@@ -130,12 +121,12 @@ fn basic_attributes() { + .unwrap() + .max_retries(0) + .return_on_404(true) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = aliyun::AliyunProvider { client }; + + let v = provider.attributes().unwrap(); + assert_eq!(v, attributes); + +- mockito::reset(); ++ server.reset(); + provider.attributes().unwrap_err(); + } +diff --git a/src/providers/aws/mock_tests.rs b/src/providers/aws/mock_tests.rs +index 2542ad9b5845..456ebb0f1247 100644 +--- a/src/providers/aws/mock_tests.rs ++++ b/src/providers/aws/mock_tests.rs +@@ -8,34 +8,29 @@ use mockito; + #[test] + fn test_aws_basic() { + let ep = "/2021-01-03/meta-data/public-keys"; ++ let mut server = mockito::Server::new(); + let client = crate::retry::Client::try_new() + .context("failed to create http client") + .unwrap() + .max_retries(0) + .return_on_404(true) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = aws::AwsProvider { client }; + + provider.fetch_ssh_keys().unwrap_err(); + +- { +- let _m503 = mockito::mock("GET", ep).with_status(503).create(); +- provider.fetch_ssh_keys().unwrap_err(); +- } ++ server.mock("GET", ep).with_status(503).create(); ++ provider.fetch_ssh_keys().unwrap_err(); + +- { +- let _m200 = mockito::mock("GET", ep).with_status(200).create(); +- let v = provider.fetch_ssh_keys().unwrap(); +- assert_eq!(v.len(), 0); +- } ++ server.mock("GET", ep).with_status(200).create(); ++ let v = provider.fetch_ssh_keys().unwrap(); ++ assert_eq!(v.len(), 0); + +- { +- let _m404 = mockito::mock("GET", ep).with_status(404).create(); +- let v = provider.fetch_ssh_keys().unwrap(); +- assert_eq!(v.len(), 0); +- } ++ server.mock("GET", ep).with_status(404).create(); ++ let v = provider.fetch_ssh_keys().unwrap(); ++ assert_eq!(v.len(), 0); + +- mockito::reset(); ++ server.reset(); + provider.fetch_ssh_keys().unwrap_err(); + } + +@@ -87,13 +82,13 @@ fn aws_get_maps() -> ( + fn test_aws_attributes() { + let (endpoints, attributes) = aws_get_maps(); + +- let mut mocks = Vec::with_capacity(endpoints.len()); ++ let mut server = mockito::Server::new(); + for (endpoint, body) in endpoints { +- let m = mockito::mock("GET", endpoint) ++ server ++ .mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); +- mocks.push(m); + } + + let client = crate::retry::Client::try_new() +@@ -101,13 +96,13 @@ fn test_aws_attributes() { + .unwrap() + .max_retries(0) + .return_on_404(true) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = aws::AwsProvider { client }; + + let v = provider.attributes().unwrap(); + assert_eq!(v, attributes); + +- mockito::reset(); ++ server.reset(); + provider.attributes().unwrap_err(); + } + +@@ -115,23 +110,24 @@ fn test_aws_attributes() { + fn test_aws_imds_version1() { + let (endpoints, attributes) = aws_get_maps(); + ++ let mut server = mockito::Server::new(); + let client = crate::retry::Client::try_new() + .context("failed to create http client") + .unwrap() + .max_retries(0) + .return_on_404(true) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + +- let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints.clone() { +- let m = mockito::mock("GET", endpoint) ++ server ++ .mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); +- mocks.push(m); + } + +- let _m = mockito::mock("PUT", "/latest/api/token") ++ server ++ .mock("PUT", "/latest/api/token") + .match_header("X-aws-ec2-metadata-token-ttl-seconds", "21600") + .with_status(403) + .with_body("Forbidden") +@@ -142,8 +138,7 @@ fn test_aws_imds_version1() { + let v = provider.attributes().unwrap(); + assert_eq!(v, attributes); + +- drop(mocks); +- mockito::reset(); ++ server.reset(); + provider.attributes().unwrap_err(); + } + +@@ -151,25 +146,26 @@ fn test_aws_imds_version1() { + fn test_aws_imds_version2() { + let (endpoints, attributes) = aws_get_maps(); + ++ let mut server = mockito::Server::new(); + let client = crate::retry::Client::try_new() + .context("failed to create http client") + .unwrap() + .max_retries(0) + .return_on_404(true) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + + let token = "test-api-token"; +- let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints.clone() { +- let m = mockito::mock("GET", endpoint) ++ server ++ .mock("GET", endpoint) + .match_header("X-aws-ec2-metadata-token", token) + .with_status(200) + .with_body(body) + .create(); +- mocks.push(m); + } + +- let _m = mockito::mock("PUT", "/latest/api/token") ++ server ++ .mock("PUT", "/latest/api/token") + .match_header("X-aws-ec2-metadata-token-ttl-seconds", "21600") + .with_status(200) + .with_body(token) +@@ -180,7 +176,6 @@ fn test_aws_imds_version2() { + let v = provider.attributes().unwrap(); + assert_eq!(v, attributes); + +- drop(mocks); +- mockito::reset(); ++ server.reset(); + provider.attributes().unwrap_err(); + } +diff --git a/src/providers/cloudstack/mock_tests.rs b/src/providers/cloudstack/mock_tests.rs +index d1b4456527dc..33b34238074f 100644 +--- a/src/providers/cloudstack/mock_tests.rs ++++ b/src/providers/cloudstack/mock_tests.rs +@@ -3,16 +3,15 @@ use crate::providers::MetadataProvider; + + #[test] + fn test_ssh_keys() { ++ let mut server = mockito::Server::new(); + let mut provider = CloudstackNetwork::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + + let key1 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsXe6CfHl45kCIzMF92VhDf2NpBWUyS1+IiTtxm5a83mT9730Hb8xim7GYeJu47kiESw2DAN8vNJ/Irg0apZ217ah2rXXjPQuWYSXuEuap8yLBSjqw8exgqVj/kzW+YqmnHASxI13eoFDxTQQGzyqbqowvxu/5gQmDwBmNAa9bT809ziB/qmpS1mD6qyyFDpR23kUwu3TkgAbwMXBDoqK+pdwfaF9uo9XaLHNEH8lD5BZuG2BeDafm2o76DhNSo83MvcCPNXKLxu3BbX/FCMFO6O8RRqony4i91fEV1b8TbXrbJz1bwEYEnJRvmjnqI/389tQFeYvplXR2WdT9PCKyEAG+j8y6XgecIcdTqV/7gFfak1mp2S7mYHZDnXixsn3MjCP/cIxxJVDitKusnj1TdFqtSXl4tqGccbg/5Sqnt/EVSK4bGwwBxv/YmE0P9cbXLxuEVI0JYzgrQvC8TtUgd8kUu2jqi1/Yj9IWm3aFsl/hhh8YwYrv/gm8PV0TxkM= root@example1"; + let key2 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDj6FBVgkTt7/DB93VVLk6304Nx7WUjLBJDSCh38zjCimHUpeo9uYDxflfu2N1CLtrSImIKBVP/JRy9g7K4zmRAH/wXw2UxYziX+hZoFIpbW3GmYQqhjx2lDvIRXJI7blhHhTUNWX5f10lFAYOLqA9J859AB1w7ND09+MS3jQgSazCx17h+QZ0qQ6kLSfnXw9PMUOE1Xba9hD1nYj14ryTVj9jrFPMFuUfXdb/G9lsDJ+cGvdE2/RMuPfDmEdo04zvZ5fQJJKvS7OyAuYev4Y+JC8MhEr756ITDZ17yq4BEMo/8rNPxZ5Von/8xnvry+8/2C3ep9rZyHtCwpRb6WT6TndV2ddXKhEIneyd1XiOcWPJguHj5vSoMN3mo8k2PvznGauvxBstvpjUSFLQu869/ZQwyMnbQi3wnkJk5CpLXePXn1J9njocJjt8+SKGijmmIAsmYosx8gmmu3H1mvq9Wi0qqWDITMm+J24AZBEPBhwVrjhLZb5MKxylF6JFJJBs= root@example2"; + +- let _m = mockito::mock("GET", "/latest/meta-data/public-keys") ++ server ++ .mock("GET", "/latest/meta-data/public-keys") + .with_status(200) + .with_body(format!("{}\n{}", key1, key2)) + .create(); +@@ -25,23 +24,22 @@ fn test_ssh_keys() { + assert_eq!(keys[1].options, None); + assert_eq!(keys[1].comment, Some("root@example2".to_string())); + +- mockito::reset(); ++ server.reset(); + provider.ssh_keys().unwrap_err(); + } + + #[test] + fn test_ssh_keys_404_ok() { ++ let mut server = mockito::Server::new(); + let mut provider = CloudstackNetwork::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + +- let _m = mockito::mock("GET", "/latest/meta-data/public-keys") ++ server ++ .mock("GET", "/latest/meta-data/public-keys") + .with_status(404) + .create(); + let v = provider.ssh_keys().unwrap(); + assert_eq!(v.len(), 0); +- mockito::reset(); ++ server.reset(); + provider.ssh_keys().unwrap_err(); + } +diff --git a/src/providers/exoscale/mock_tests.rs b/src/providers/exoscale/mock_tests.rs +index b0d80fdc930c..9c4c4d0f3fab 100644 +--- a/src/providers/exoscale/mock_tests.rs ++++ b/src/providers/exoscale/mock_tests.rs +@@ -7,48 +7,40 @@ fn basic_hostname() { + let ep = "/1.0/meta-data/local-hostname"; + let hostname = "test-hostname"; + ++ let mut server = mockito::Server::new(); + let mut provider = exoscale::ExoscaleProvider::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + +- { +- let _m503 = mockito::mock("GET", ep).with_status(503).create(); +- provider.hostname().unwrap_err(); +- } ++ server.mock("GET", ep).with_status(503).create(); ++ provider.hostname().unwrap_err(); + +- { +- let _m200 = mockito::mock("GET", ep) +- .with_status(200) +- .with_body(hostname) +- .create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, Some(hostname.to_string())); +- } ++ server ++ .mock("GET", ep) ++ .with_status(200) ++ .with_body(hostname) ++ .create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, Some(hostname.to_string())); + +- { +- let _m200_empty = mockito::mock("GET", ep) +- .with_status(200) +- .with_body("") +- .create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, None); +- } ++ server ++ .mock("GET", ep) ++ .with_status(200) ++ .with_body("") ++ .create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, None); + +- mockito::reset(); ++ server.reset(); + provider.hostname().unwrap_err(); + } + + #[test] + fn basic_pubkeys() { ++ let mut server = mockito::Server::new(); + let mut provider = exoscale::ExoscaleProvider::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + +- let _m_keys = mockito::mock("GET", "/1.0/meta-data/public-keys") ++ server.mock("GET", "/1.0/meta-data/public-keys") + .with_status(200) + .with_body("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+bqdi18/+JfjrqmOEtVKyCU0bsIc6tBqqU7p9mesJkALocLddDU6d97w2zwERhzaqReDyg4msvQQohgtncb4afKKWQjCCCWlcwtP0nAeg9GFtUfmLeYcP2KAjxblabncluuAnvMHyBixKAjr5eWD4B1HjOmpMRmycwmy85QhGTYhF+AkiHGCPPUDrVy2cIvrPSDXEEa7bz5aQUime0Eold56n3O7E5BJuAozf+oeiWCERRRt9ATlLkMvwVItzBHN25YoMOd0KfgYMtBVAw86TErYFx4Tu98blYNUQTthf9VxcU8xy0rFacXmuS7LHbp+CKDY0X5dNHuhqz0wFto4J test-comment") + .create(); +@@ -60,7 +52,7 @@ fn basic_pubkeys() { + assert_eq!(keys[0].options, None); + assert_eq!(keys[0].comment, Some("test-comment".to_string())); + +- mockito::reset(); ++ server.reset(); + provider.ssh_keys().unwrap_err(); + } + +@@ -87,13 +79,13 @@ fn basic_attributes() { + "/1.0/meta-data/cloud-identifier" => cloud_identifier, + "/1.0/meta-data/vm-id" => vm_id, + }; +- let mut mocks = Vec::with_capacity(endpoints.len()); ++ let mut server = mockito::Server::new(); + for (endpoint, body) in endpoints { +- let m = mockito::mock("GET", endpoint) ++ server ++ .mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); +- mocks.push(m); + } + + let attributes = maplit::hashmap! { +@@ -112,12 +104,12 @@ fn basic_attributes() { + .unwrap() + .max_retries(0) + .return_on_404(true) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = exoscale::ExoscaleProvider { client }; + + let v = provider.attributes().unwrap(); + assert_eq!(v, attributes); + +- mockito::reset(); ++ server.reset(); + provider.attributes().unwrap_err(); + } +diff --git a/src/providers/gcp/mock_tests.rs b/src/providers/gcp/mock_tests.rs +index 4cfadab7b632..a61aa4f9a67e 100644 +--- a/src/providers/gcp/mock_tests.rs ++++ b/src/providers/gcp/mock_tests.rs +@@ -7,33 +7,26 @@ fn basic_hostname() { + let ep = "/computeMetadata/v1/instance/hostname"; + let hostname = "test-hostname"; + ++ let mut server = mockito::Server::new(); + let mut provider = gcp::GcpProvider::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + +- { +- let _m503 = mockito::mock("GET", ep).with_status(503).create(); +- provider.hostname().unwrap_err(); +- } ++ server.mock("GET", ep).with_status(503).create(); ++ provider.hostname().unwrap_err(); + +- { +- let _m200 = mockito::mock("GET", ep) +- .with_status(200) +- .with_body(hostname) +- .create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, Some(hostname.to_string())); +- } ++ server ++ .mock("GET", ep) ++ .with_status(200) ++ .with_body(hostname) ++ .create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, Some(hostname.to_string())); + +- { +- let _m404 = mockito::mock("GET", ep).with_status(404).create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, None); +- } ++ server.mock("GET", ep).with_status(404).create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, None); + +- mockito::reset(); ++ server.reset(); + provider.hostname().unwrap_err(); + } + +@@ -50,13 +43,13 @@ fn basic_attributes() { + "/computeMetadata/v1/instance/network-interfaces/0/ip" => ip_local, + "/computeMetadata/v1/instance/machine-type" => machine_type, + }; +- let mut mocks = Vec::with_capacity(endpoints.len()); ++ let mut server = mockito::Server::new(); + for (endpoint, body) in endpoints { +- let m = mockito::mock("GET", endpoint) ++ server ++ .mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); +- mocks.push(m); + } + + let attributes = maplit::hashmap! { +@@ -70,12 +63,12 @@ fn basic_attributes() { + .unwrap() + .max_retries(0) + .return_on_404(true) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = gcp::GcpProvider { client }; + + let v = provider.attributes().unwrap(); + assert_eq!(v, attributes); + +- mockito::reset(); ++ server.reset(); + provider.attributes().unwrap_err(); + } +diff --git a/src/providers/microsoft/azure/mock_tests.rs b/src/providers/microsoft/azure/mock_tests.rs +index ebe1526cca7c..f658d015b3fc 100644 +--- a/src/providers/microsoft/azure/mock_tests.rs ++++ b/src/providers/microsoft/azure/mock_tests.rs +@@ -67,7 +67,7 @@ static GOALSTATE_BODY_NO_CERTS: &str = r#" + + "#; + +-fn mock_fab_version() -> mockito::Mock { ++fn mock_fab_version(server: &mut mockito::Server) -> mockito::Mock { + let fab_version = "/?comp=versions"; + let ver_body = r#" + +@@ -88,13 +88,14 @@ fn mock_fab_version() -> mockito::Mock { + + "#; + +- mockito::mock("GET", fab_version) ++ server ++ .mock("GET", fab_version) + .with_body(ver_body) + .with_status(200) + .create() + } + +-fn mock_goalstate(with_certificates: bool) -> mockito::Mock { ++fn mock_goalstate(server: &mut mockito::Server, with_certificates: bool) -> mockito::Mock { + let fab_goalstate = "/machine/?comp=goalstate"; + + let gs_body = if with_certificates { +@@ -103,7 +104,8 @@ fn mock_goalstate(with_certificates: bool) -> mockito::Mock { + GOALSTATE_BODY_NO_CERTS + }; + +- mockito::mock("GET", fab_goalstate) ++ server ++ .mock("GET", fab_goalstate) + .with_body(gs_body) + .with_status(200) + .create() +@@ -111,11 +113,13 @@ fn mock_goalstate(with_certificates: bool) -> mockito::Mock { + + #[test] + fn test_boot_checkin() { +- let m_version = mock_fab_version(); +- let m_goalstate = mock_goalstate(true); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); ++ let m_goalstate = mock_goalstate(&mut server, true); + + let fab_health = "/machine/?comp=health"; +- let m_health = mockito::mock("POST", fab_health) ++ let m_health = server ++ .mock("POST", fab_health) + .match_header("content-type", Matcher::Regex("text/xml".to_string())) + .match_header("x-ms-version", Matcher::Regex("2012-11-30".to_string())) + .match_body(Matcher::Regex("Ready".to_string())) +@@ -127,7 +131,7 @@ fn test_boot_checkin() { + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azure::Azure::with_client(Some(client)).unwrap(); + let r = provider.boot_checkin(); + +@@ -136,23 +140,25 @@ fn test_boot_checkin() { + m_health.assert(); + r.unwrap(); + +- mockito::reset(); ++ server.reset(); + + // Check error logic, but fail fast without re-trying. + let client = retry::Client::try_new() + .unwrap() + .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + + #[test] + fn test_hostname() { +- let m_version = mock_fab_version(); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); + + let testname = "testname"; + let endpoint = "/metadata/instance/compute/name?api-version=2017-08-01&format=text"; +- let m_hostname = mockito::mock("GET", endpoint) ++ let m_hostname = server ++ .mock("GET", endpoint) + .match_header("Metadata", "true") + .with_body(testname) + .with_status(200) +@@ -160,7 +166,7 @@ fn test_hostname() { + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azure::Azure::with_client(Some(client)).unwrap(); + let r = provider.hostname().unwrap(); + +@@ -170,23 +176,25 @@ fn test_hostname() { + let hostname = r.unwrap(); + assert_eq!(hostname, testname); + +- mockito::reset(); ++ server.reset(); + + // Check error logic, but fail fast without re-trying. + let client = retry::Client::try_new() + .unwrap() + .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + + #[test] + fn test_vmsize() { +- let m_version = mock_fab_version(); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); + + let testvmsize = "testvmsize"; + let endpoint = "/metadata/instance/compute/vmSize?api-version=2017-08-01&format=text"; +- let m_vmsize = mockito::mock("GET", endpoint) ++ let m_vmsize = server ++ .mock("GET", endpoint) + .match_header("Metadata", "true") + .with_body(testvmsize) + .with_status(200) +@@ -194,7 +202,7 @@ fn test_vmsize() { + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azure::Azure::with_client(Some(client)).unwrap(); + let attributes = provider.attributes().unwrap(); + let r = attributes.get("AZURE_VMSIZE"); +@@ -205,24 +213,25 @@ fn test_vmsize() { + let vmsize = r.unwrap(); + assert_eq!(vmsize, testvmsize); + +- mockito::reset(); ++ server.reset(); + + // Check error logic, but fail fast without re-trying. + let client = retry::Client::try_new() + .unwrap() + .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + azure::Azure::with_client(Some(client)).unwrap_err(); + } + + #[test] + fn test_goalstate_certs() { +- let m_version = mock_fab_version(); +- let m_goalstate = mock_goalstate(true); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); ++ let m_goalstate = mock_goalstate(&mut server, true); + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azure::Azure::with_client(Some(client)).unwrap(); + let goalstate = provider.fetch_goalstate().unwrap(); + +@@ -233,17 +242,18 @@ fn test_goalstate_certs() { + let certs_url = reqwest::Url::parse(&ep).unwrap(); + assert_eq!(certs_url.scheme(), "http"); + +- mockito::reset(); ++ server.reset(); + } + + #[test] + fn test_goalstate_no_certs() { +- let m_version = mock_fab_version(); +- let m_goalstate = mock_goalstate(false); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); ++ let m_goalstate = mock_goalstate(&mut server, false); + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azure::Azure::with_client(Some(client)).unwrap(); + let goalstate = provider.fetch_goalstate().unwrap(); + +@@ -252,5 +262,5 @@ fn test_goalstate_no_certs() { + + assert_eq!(goalstate.certs_endpoint(), None); + +- mockito::reset(); ++ server.reset(); + } +diff --git a/src/providers/microsoft/azurestack/mock_tests.rs b/src/providers/microsoft/azurestack/mock_tests.rs +index 83141dcec330..d861a4e080ff 100644 +--- a/src/providers/microsoft/azurestack/mock_tests.rs ++++ b/src/providers/microsoft/azurestack/mock_tests.rs +@@ -67,7 +67,7 @@ static GOALSTATE_BODY_NO_CERTS: &str = r#" + + "#; + +-fn mock_fab_version() -> mockito::Mock { ++fn mock_fab_version(server: &mut mockito::Server) -> mockito::Mock { + let fab_version = "/?comp=versions"; + let ver_body = r#" + +@@ -88,13 +88,14 @@ fn mock_fab_version() -> mockito::Mock { + + "#; + +- mockito::mock("GET", fab_version) ++ server ++ .mock("GET", fab_version) + .with_body(ver_body) + .with_status(200) + .create() + } + +-fn mock_goalstate(with_certificates: bool) -> mockito::Mock { ++fn mock_goalstate(server: &mut mockito::Server, with_certificates: bool) -> mockito::Mock { + let fab_goalstate = "/machine/?comp=goalstate"; + + let gs_body = if with_certificates { +@@ -103,7 +104,8 @@ fn mock_goalstate(with_certificates: bool) -> mockito::Mock { + GOALSTATE_BODY_NO_CERTS + }; + +- mockito::mock("GET", fab_goalstate) ++ server ++ .mock("GET", fab_goalstate) + .with_body(gs_body) + .with_status(200) + .create() +@@ -111,11 +113,13 @@ fn mock_goalstate(with_certificates: bool) -> mockito::Mock { + + #[test] + fn test_boot_checkin() { +- let m_version = mock_fab_version(); +- let m_goalstate = mock_goalstate(true); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); ++ let m_goalstate = mock_goalstate(&mut server, true); + + let fab_health = "/machine/?comp=health"; +- let m_health = mockito::mock("POST", fab_health) ++ let m_health = server ++ .mock("POST", fab_health) + .match_header("content-type", Matcher::Regex("text/xml".to_string())) + .match_header("x-ms-version", Matcher::Regex("2012-11-30".to_string())) + .match_body(Matcher::Regex("Ready".to_string())) +@@ -127,7 +131,7 @@ fn test_boot_checkin() { + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); + let r = provider.boot_checkin(); + +@@ -136,7 +140,7 @@ fn test_boot_checkin() { + m_health.assert(); + r.unwrap(); + +- mockito::reset(); ++ server.reset(); + + // Check error logic, but fail fast without re-trying. + let client = retry::Client::try_new().unwrap().max_retries(0); +@@ -145,12 +149,14 @@ fn test_boot_checkin() { + + #[test] + fn test_identity() { +- let m_version = mock_fab_version(); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); + + let testname = "testName"; // TODO clean up response composition + let json_response = r#"{"subscriptionId":"testID","vmName":"testName"}"#; + let endpoint = "/Microsoft.Compute/identity?api-version=2019-03-11"; +- let m_identity = mockito::mock("GET", endpoint) ++ let m_identity = server ++ .mock("GET", endpoint) + .match_header("Metadata", "true") + .with_body(json_response) + .with_status(200) +@@ -158,7 +164,7 @@ fn test_identity() { + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); + let r = provider.hostname().unwrap(); + +@@ -168,7 +174,7 @@ fn test_identity() { + let hostname = r.unwrap(); + assert_eq!(hostname, testname); + +- mockito::reset(); ++ server.reset(); + + // Check error logic, but fail fast without re-trying. + let client = retry::Client::try_new().unwrap().max_retries(0); +@@ -177,12 +183,14 @@ fn test_identity() { + + #[test] + fn test_hostname() { +- let m_version = mock_fab_version(); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); + + let testname = "testName"; // TODO clean up response composition + let json_response = r#"{"subscriptionId":"testID","vmName":"testName"}"#; + let endpoint = "/Microsoft.Compute/identity?api-version=2019-03-11"; +- let m_identity = mockito::mock("GET", endpoint) ++ let m_identity = server ++ .mock("GET", endpoint) + .match_header("Metadata", "true") + .with_body(json_response) + .with_status(200) +@@ -190,7 +198,7 @@ fn test_hostname() { + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); + let r = provider.hostname().unwrap(); + +@@ -200,7 +208,7 @@ fn test_hostname() { + let hostname = r.unwrap(); + assert_eq!(hostname, testname); + +- mockito::reset(); ++ server.reset(); + + // Check error logic, but fail fast without re-trying. + let client = retry::Client::try_new().unwrap().max_retries(0); +@@ -209,12 +217,13 @@ fn test_hostname() { + + #[test] + fn test_goalstate_certs() { +- let m_version = mock_fab_version(); +- let m_goalstate = mock_goalstate(true); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); ++ let m_goalstate = mock_goalstate(&mut server, true); + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); + let goalstate = provider.fetch_goalstate().unwrap(); + +@@ -225,17 +234,18 @@ fn test_goalstate_certs() { + let certs_url = reqwest::Url::parse(&ep).unwrap(); + assert_eq!(certs_url.scheme(), "http"); + +- mockito::reset(); ++ server.reset(); + } + + #[test] + fn test_goalstate_no_certs() { +- let m_version = mock_fab_version(); +- let m_goalstate = mock_goalstate(false); ++ let mut server = mockito::Server::new(); ++ let m_version = mock_fab_version(&mut server); ++ let m_goalstate = mock_goalstate(&mut server, false); + + let client = retry::Client::try_new() + .unwrap() +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = azurestack::AzureStack::with_client(Some(client)).unwrap(); + let goalstate = provider.fetch_goalstate().unwrap(); + +@@ -244,5 +254,5 @@ fn test_goalstate_no_certs() { + + assert_eq!(goalstate.certs_endpoint(), None); + +- mockito::reset(); ++ server.reset(); + } +diff --git a/src/providers/openstack/mock_tests.rs b/src/providers/openstack/mock_tests.rs +index d1d47e62bd88..2dc6f161a862 100644 +--- a/src/providers/openstack/mock_tests.rs ++++ b/src/providers/openstack/mock_tests.rs +@@ -4,11 +4,9 @@ use mockito; + + #[test] + fn test_ssh_keys() { ++ let mut server = mockito::Server::new(); + let mut provider = OpenstackProviderNetwork::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + + let key1 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsXe6CfHl45kCIzMF92VhDf2NpBWUyS1+IiTtxm5a83mT9730Hb8xim7GYeJu47kiESw2DAN8vNJ/Irg0apZ217ah2rXXjPQuWYSXuEuap8yLBSjqw8exgqVj/kzW+YqmnHASxI13eoFDxTQQGzyqbqowvxu/5gQmDwBmNAa9bT809ziB/qmpS1mD6qyyFDpR23kUwu3TkgAbwMXBDoqK+pdwfaF9uo9XaLHNEH8lD5BZuG2BeDafm2o76DhNSo83MvcCPNXKLxu3BbX/FCMFO6O8RRqony4i91fEV1b8TbXrbJz1bwEYEnJRvmjnqI/389tQFeYvplXR2WdT9PCKyEAG+j8y6XgecIcdTqV/7gFfak1mp2S7mYHZDnXixsn3MjCP/cIxxJVDitKusnj1TdFqtSXl4tqGccbg/5Sqnt/EVSK4bGwwBxv/YmE0P9cbXLxuEVI0JYzgrQvC8TtUgd8kUu2jqi1/Yj9IWm3aFsl/hhh8YwYrv/gm8PV0TxkM= root@example1"; + let key2 = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDj6FBVgkTt7/DB93VVLk6304Nx7WUjLBJDSCh38zjCimHUpeo9uYDxflfu2N1CLtrSImIKBVP/JRy9g7K4zmRAH/wXw2UxYziX+hZoFIpbW3GmYQqhjx2lDvIRXJI7blhHhTUNWX5f10lFAYOLqA9J859AB1w7ND09+MS3jQgSazCx17h+QZ0qQ6kLSfnXw9PMUOE1Xba9hD1nYj14ryTVj9jrFPMFuUfXdb/G9lsDJ+cGvdE2/RMuPfDmEdo04zvZ5fQJJKvS7OyAuYev4Y+JC8MhEr756ITDZ17yq4BEMo/8rNPxZ5Von/8xnvry+8/2C3ep9rZyHtCwpRb6WT6TndV2ddXKhEIneyd1XiOcWPJguHj5vSoMN3mo8k2PvznGauvxBstvpjUSFLQu869/ZQwyMnbQi3wnkJk5CpLXePXn1J9njocJjt8+SKGijmmIAsmYosx8gmmu3H1mvq9Wi0qqWDITMm+J24AZBEPBhwVrjhLZb5MKxylF6JFJJBs= root@example2"; +@@ -18,13 +16,12 @@ fn test_ssh_keys() { + "/latest/meta-data/public-keys/1/openssh-key" => key2, + }; + +- let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints { +- let m = mockito::mock("GET", endpoint) ++ server ++ .mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); +- mocks.push(m) + } + + let keys = provider.ssh_keys().unwrap(); +@@ -35,23 +32,22 @@ fn test_ssh_keys() { + assert_eq!(keys[1].options, None); + assert_eq!(keys[1].comment, Some("root@example2".to_string())); + +- mockito::reset(); ++ server.reset(); + provider.ssh_keys().unwrap_err(); + } + + #[test] + fn test_ssh_keys_404_ok() { ++ let mut server = mockito::Server::new(); + let mut provider = OpenstackProviderNetwork::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + +- let _m = mockito::mock("GET", "/latest/meta-data/public-keys") ++ server ++ .mock("GET", "/latest/meta-data/public-keys") + .with_status(404) + .create(); + let v = provider.ssh_keys().unwrap(); + assert_eq!(v.len(), 0); +- mockito::reset(); ++ server.reset(); + provider.ssh_keys().unwrap_err(); + } +diff --git a/src/providers/packet/mock_tests.rs b/src/providers/packet/mock_tests.rs +index c2027a77c468..e5e648f12af1 100644 +--- a/src/providers/packet/mock_tests.rs ++++ b/src/providers/packet/mock_tests.rs +@@ -3,10 +3,11 @@ use mockito::{self, Matcher}; + + #[test] + fn test_boot_checkin() { ++ let mut server = mockito::Server::new(); + let client = crate::retry::Client::try_new() + .unwrap() + .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let data = packet::PacketData { + id: String::new(), + hostname: String::new(), +@@ -21,14 +22,15 @@ fn test_boot_checkin() { + bonding: packet::PacketBondingMode { mode: 0 }, + }, + error: None, +- phone_home_url: mockito::server_url(), ++ phone_home_url: server.url(), + }; + let provider = packet::PacketProvider { + client: client.clone(), + data, + }; + +- let mock = mockito::mock("POST", "/") ++ let mock = server ++ .mock("POST", "/") + .match_header( + "content-type", + Matcher::Regex("application/json".to_string()), +@@ -41,7 +43,7 @@ fn test_boot_checkin() { + mock.assert(); + r.unwrap(); + +- mockito::reset(); ++ server.reset(); + + // Check error logic, but fail fast without re-trying. + packet::PacketProvider::fetch_content(Some(client)).unwrap_err(); +@@ -116,7 +118,9 @@ fn test_packet_attributes() { + "PACKET_IPV6_PRIVATE_GATEWAY_0".to_string() => "fd00::".to_string(), + }; + +- let _m = mockito::mock("GET", "/metadata") ++ let mut server = mockito::Server::new(); ++ server ++ .mock("GET", "/metadata") + .with_status(200) + .with_body(metadata) + .create(); +@@ -124,18 +128,18 @@ fn test_packet_attributes() { + let client = crate::retry::Client::try_new() + .unwrap() + .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = packet::PacketProvider::fetch_content(Some(client)).unwrap(); + let v = provider.attributes().unwrap(); + + assert_eq!(v, attributes); + +- mockito::reset(); ++ server.reset(); + + // Check error logic, but fail fast without re-trying. + let client = crate::retry::Client::try_new() + .unwrap() + .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + packet::PacketProvider::fetch_content(Some(client)).unwrap_err(); + } +diff --git a/src/providers/vultr/mock_tests.rs b/src/providers/vultr/mock_tests.rs +index 34878e869224..83bc8b629e45 100644 +--- a/src/providers/vultr/mock_tests.rs ++++ b/src/providers/vultr/mock_tests.rs +@@ -7,54 +7,44 @@ fn test_hostname() { + let ep = "/v1/hostname"; + let hostname = "test-hostname"; + ++ let mut server = mockito::Server::new(); + let mut provider = vultr::VultrProvider::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + +- { +- let _m503 = mockito::mock("GET", ep).with_status(503).create(); +- provider.hostname().unwrap_err(); +- } ++ server.mock("GET", ep).with_status(503).create(); ++ provider.hostname().unwrap_err(); + +- { +- let _m200 = mockito::mock("GET", ep) +- .with_status(200) +- .with_body(hostname) +- .create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, Some(hostname.to_string())); +- } ++ server ++ .mock("GET", ep) ++ .with_status(200) ++ .with_body(hostname) ++ .create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, Some(hostname.to_string())); + +- { +- let _m404 = mockito::mock("GET", ep).with_status(404).create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, None); +- } ++ server.mock("GET", ep).with_status(404).create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, None); + +- { +- let _m200_empty = mockito::mock("GET", ep) +- .with_status(200) +- .with_body("") +- .create(); +- let v = provider.hostname().unwrap(); +- assert_eq!(v, None); +- } ++ server ++ .mock("GET", ep) ++ .with_status(200) ++ .with_body("") ++ .create(); ++ let v = provider.hostname().unwrap(); ++ assert_eq!(v, None); + +- mockito::reset(); ++ server.reset(); + provider.hostname().unwrap_err(); + } + + #[test] + fn test_pubkeys() { ++ let mut server = mockito::Server::new(); + let mut provider = vultr::VultrProvider::try_new().unwrap(); +- provider.client = provider +- .client +- .max_retries(0) +- .mock_base_url(mockito::server_url()); ++ provider.client = provider.client.max_retries(0).mock_base_url(server.url()); + +- let _m_keys = mockito::mock("GET", "/v1/public-keys") ++ server.mock("GET", "/v1/public-keys") + .with_status(200) + .with_body("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsXe6CfHl45kCIzMF92VhDf2NpBWUyS1+IiTtxm5a83mT9730Hb8xim7GYeJu47kiESw2DAN8vNJ/Irg0apZ217ah2rXXjPQuWYSXuEuap8yLBSjqw8exgqVj/kzW+YqmnHASxI13eoFDxTQQGzyqbqowvxu/5gQmDwBmNAa9bT809ziB/qmpS1mD6qyyFDpR23kUwu3TkgAbwMXBDoqK+pdwfaF9uo9XaLHNEH8lD5BZuG2BeDafm2o76DhNSo83MvcCPNXKLxu3BbX/FCMFO6O8RRqony4i91fEV1b8TbXrbJz1bwEYEnJRvmjnqI/389tQFeYvplXR2WdT9PCKyEAG+j8y6XgecIcdTqV/7gFfak1mp2S7mYHZDnXixsn3MjCP/cIxxJVDitKusnj1TdFqtSXl4tqGccbg/5Sqnt/EVSK4bGwwBxv/YmE0P9cbXLxuEVI0JYzgrQvC8TtUgd8kUu2jqi1/Yj9IWm3aFsl/hhh8YwYrv/gm8PV0TxkM= root@example1\n + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDj6FBVgkTt7/DB93VVLk6304Nx7WUjLBJDSCh38zjCimHUpeo9uYDxflfu2N1CLtrSImIKBVP/JRy9g7K4zmRAH/wXw2UxYziX+hZoFIpbW3GmYQqhjx2lDvIRXJI7blhHhTUNWX5f10lFAYOLqA9J859AB1w7ND09+MS3jQgSazCx17h+QZ0qQ6kLSfnXw9PMUOE1Xba9hD1nYj14ryTVj9jrFPMFuUfXdb/G9lsDJ+cGvdE2/RMuPfDmEdo04zvZ5fQJJKvS7OyAuYev4Y+JC8MhEr756ITDZ17yq4BEMo/8rNPxZ5Von/8xnvry+8/2C3ep9rZyHtCwpRb6WT6TndV2ddXKhEIneyd1XiOcWPJguHj5vSoMN3mo8k2PvznGauvxBstvpjUSFLQu869/ZQwyMnbQi3wnkJk5CpLXePXn1J9njocJjt8+SKGijmmIAsmYosx8gmmu3H1mvq9Wi0qqWDITMm+J24AZBEPBhwVrjhLZb5MKxylF6JFJJBs= root@example2") +@@ -70,7 +60,7 @@ fn test_pubkeys() { + assert_eq!(keys[1].options, None); + assert_eq!(keys[1].comment, Some("root@example2".to_string())); + +- mockito::reset(); ++ server.reset(); + provider.ssh_keys().unwrap_err(); + } + +@@ -86,13 +76,13 @@ fn test_attributes() { + "/v1/region/regioncode" => regioncode, + }; + +- let mut mocks = Vec::with_capacity(endpoints.len()); ++ let mut server = mockito::Server::new(); + for (endpoint, body) in endpoints { +- let m = mockito::mock("GET", endpoint) ++ server ++ .mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); +- mocks.push(m) + } + + let attributes = maplit::hashmap! { +@@ -105,12 +95,12 @@ fn test_attributes() { + .unwrap() + .max_retries(0) + .return_on_404(true) +- .mock_base_url(mockito::server_url()); ++ .mock_base_url(server.url()); + let provider = vultr::VultrProvider { client }; + + let v = provider.attributes().unwrap(); + assert_eq!(v, attributes); + +- mockito::reset(); ++ server.reset(); + provider.attributes().unwrap_err(); + } +-- +2.39.2 + diff --git a/0007-Bump-mockito-version.patch b/0007-Bump-mockito-version.patch new file mode 100644 index 0000000..1b3e03f --- /dev/null +++ b/0007-Bump-mockito-version.patch @@ -0,0 +1,9 @@ +diff -ur a/Cargo.toml b/Cargo.toml +--- a/Cargo.toml 1969-12-31 19:00:01.000000000 -0500 ++++ b/Cargo.toml 2023-03-20 20:44:02.135392305 -0400 +@@ -132,4 +132,4 @@ + version = ">= 2.3, < 4" + + [dev-dependencies.mockito] +-version = ">= 0.29, < 0.32" ++version = "1" diff --git a/rust-afterburn.spec b/rust-afterburn.spec index 4471ad0..7f686e5 100644 --- a/rust-afterburn.spec +++ b/rust-afterburn.spec @@ -8,7 +8,7 @@ Name: rust-%{crate} Version: 5.4.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Simple cloud provider agent # Upstream license specification: Apache-2.0 @@ -18,6 +18,16 @@ Source0: %{crates_source} # not used on Fedora Source1: https://github.com/coreos/%{crate}/releases/download/v%{version}/%{crate}-%{version}-vendor.tar.gz +# Use rust-mockito 1.0 API +# Based on https://github.com/coreos/afterburn/pull/894, fixing merge conflicts +Patch0: 0001-providers-packet-use-stored-client-for-boot-checkin.patch +Patch1: 0002-providers-microsoft-use-stored-client-for-all-fetche.patch +Patch2: 0003-providers-microsoft-import-crate-retry.patch +Patch3: 0004-retry-client-move-URL-parsing-into-helper-function.patch +Patch4: 0005-providers-move-endpoint-mocking-into-retry-Client.patch +Patch5: 0006-Update-mockito-to-1.0.patch +Patch6: 0007-Bump-mockito-version.patch + ExclusiveArch: %{rust_arches} %if 0%{?rhel} && !0%{?eln} BuildRequires: rust-toolset @@ -143,6 +153,9 @@ cp -a dracut/* %{buildroot}%{dracutmodulesdir} %endif %changelog +* Mon Mar 20 2023 Benjamin Gilbert - 5.4.0-2 +- Update for Mockito 1.0 API + * Fri Feb 03 2023 Benjamin Gilbert - 5.4.0-1 - Update to 5.4.0