rust-afterburn/0005-providers-move-endpoint-mocking-into-retry-Client.patch
2023-03-20 20:46:22 -04:00

1048 lines
40 KiB
Diff

From 6da8cac456dc6cf8a53f99ad9c46b5fccb010c20 Mon Sep 17 00:00:00 2001
From: Benjamin Gilbert <bgilbert@redhat.com>
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<String> {
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<String>,
}
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<D>(&self, d: D, url: String) -> RequestBuilder<D>
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<String>,
}
impl<D> RequestBuilder<D>
@@ -310,7 +328,24 @@ where
}
fn parse_url(&self) -> Result<reqwest::Url> {
- 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