From 860ff338a9cd1b61428803297ad6f42e3f7b52c2 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Tue, 1 Oct 2019 12:09:49 -0400 Subject: [PATCH 01/12] aws/mod.rs: fetch instance-type for aws Adds instances-type to the result hashmap. Reference: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-categories Signed-off-by: Zonggen Bai --- README.md | 1 + src/providers/aws/mod.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index f0322b25..7f869282 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ On CoreOS Container Linux, the supported providers and metadata are [somewhat di - AFTERBURN_AWS_IPV4_PUBLIC - AFTERBURN_AWS_AVAILABILITY_ZONE - AFTERBURN_AWS_INSTANCE_ID + - AFTERBURN_AWS_INSTANCE_TYPE - AFTERBURN_AWS_REGION - azure - SSH Keys diff --git a/src/providers/aws/mod.rs b/src/providers/aws/mod.rs index d070bee6..95dbe8fe 100644 --- a/src/providers/aws/mod.rs +++ b/src/providers/aws/mod.rs @@ -120,6 +120,11 @@ impl MetadataProvider for AwsProvider { &format!("{}_INSTANCE_ID", ENV_PREFIX), "meta-data/instance-id", )?; + add_value( + &mut out, + &format!("{}_INSTANCE_TYPE", ENV_PREFIX), + "meta-data/instance-type", + )?; add_value( &mut out, &format!("{}_IPV4_LOCAL", ENV_PREFIX), From a53efec43bc455141031d78137bee3c77a50a440 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Wed, 2 Oct 2019 14:55:12 -0400 Subject: [PATCH 02/12] providers/azure: fetch the sku as instance type Fetches sku as instance type information in Azure. Reference: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service Signed-off-by: Allen Bai --- README.md | 1 + src/providers/azure/mod.rs | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f869282..f733f685 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ On CoreOS Container Linux, the supported providers and metadata are [somewhat di - Attributes - AFTERBURN_AZURE_IPV4_DYNAMIC - AFTERBURN_AZURE_IPV4_VIRTUAL + - AFTERBURN_AZURE_SKU - cloudstack-configdrive - SSH Keys - Attributes diff --git a/src/providers/azure/mod.rs b/src/providers/azure/mod.rs index f45f43b3..769617a5 100644 --- a/src/providers/azure/mod.rs +++ b/src/providers/azure/mod.rs @@ -418,12 +418,28 @@ impl Azure { .chain_err(|| "failed to get hostname")?; Ok(name) } + + fn fetch_sku (&self) -> Result> { + const SKU_URL: &str = "metadata/instance/compute/sku?api-version=2017-08-01&format=text"; + let url = format!("{}/{}", Self::metadata_endpoint(), SKU_URL); + + let sku = retry::Client::try_new()? + .header( + HeaderName::from_static("metadata"), + HeaderValue::from_static("true"), + ) + .get(retry::Raw, url) + .send() + .chain_err(|| "failed to get sku")?; + Ok(sku) + } } impl MetadataProvider for Azure { fn attributes(&self) -> Result> { let attributes = self.get_attributes()?; - let mut out = HashMap::with_capacity(2); + let sku = self.fetch_sku()?; + let mut out = HashMap::with_capacity(3); if let Some(virtual_ipv4) = attributes.virtual_ipv4 { out.insert("AZURE_IPV4_VIRTUAL".to_string(), virtual_ipv4.to_string()); @@ -433,6 +449,10 @@ impl MetadataProvider for Azure { out.insert("AZURE_IPV4_DYNAMIC".to_string(), dynamic_ipv4.to_string()); } + if let Some(sku) = sku { + out.insert("AZURE_SKU".to_string(), sku.to_string()); + } + Ok(out) } From fb01c224028e1c446bde859ff1b69258d4a3e006 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Thu, 3 Oct 2019 11:43:38 -0400 Subject: [PATCH 03/12] providers/gcp: fetch machine-type as instance type Reference: https://cloud.google.com/compute/docs/storing-retrieving-metadata Signed-off-by: Allen Bai --- README.md | 1 + src/providers/gcp/mod.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index f733f685..2e393a87 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ On CoreOS Container Linux, the supported providers and metadata are [somewhat di - AFTERBURN_GCP_HOSTNAME - AFTERBURN_GCP_IP_EXTERNAL_0 - AFTERBURN_GCP_IP_LOCAL_0 + - AFTERBURN_GCP_MACHINE_TYPE - openstack-metadata - SSH Keys - Attributes diff --git a/src/providers/gcp/mod.rs b/src/providers/gcp/mod.rs index 1970a95e..9f887828 100644 --- a/src/providers/gcp/mod.rs +++ b/src/providers/gcp/mod.rs @@ -163,6 +163,11 @@ impl MetadataProvider for GcpProvider { &format!("{}_IP_LOCAL_0", ENV_PREFIX), "instance/network-interfaces/0/ip", )?; + add_value( + &mut out, + &format!("{}_MACHINE_TYPE", ENV_PREFIX), + "instance/machine-type", + )?; Ok(out) } From 99fc8576e6ba16df4f40535372171aca933201e3 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Thu, 3 Oct 2019 12:58:18 -0400 Subject: [PATCH 04/12] providers/openstack: fetch instance-type from openstack Reference: https://docs.openstack.org/nova/latest/user/metadata.html Signed-off-by: Allen Bai --- README.md | 1 + src/providers/openstack/network.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 2e393a87..31581bc1 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ On CoreOS Container Linux, the supported providers and metadata are [somewhat di - AFTERBURN_OPENSTACK_IPV4_LOCAL - AFTERBURN_OPENSTACK_IPV4_PUBLIC - AFTERBURN_OPENSTACK_INSTANCE_ID + - AFTERBURN_OPENSTACK_INSTANCE_TYPE - packet - SSH Keys - Network Configs diff --git a/src/providers/openstack/network.rs b/src/providers/openstack/network.rs index 223c4c1d..9797147a 100644 --- a/src/providers/openstack/network.rs +++ b/src/providers/openstack/network.rs @@ -73,6 +73,7 @@ impl MetadataProvider for OpenstackProvider { add_value(&mut out, "OPENSTACK_HOSTNAME", "hostname")?; add_value(&mut out, "OPENSTACK_INSTANCE_ID", "instance-id")?; + add_value(&mut out, "OPENSTACK_INSTANCE_TYPE", "instance-type")?; add_value(&mut out, "OPENSTACK_IPV4_LOCAL", "local-ipv4")?; add_value(&mut out, "OPENSTACK_IPV4_PUBLIC", "public-ipv4")?; From 0db1dd41931325355ddaba22025c52922fdfb2be Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Thu, 3 Oct 2019 14:50:51 -0400 Subject: [PATCH 05/12] providers/packet: fetch plan as intance type Reference: https://support.packet.com/kb/articles/metadata Signed-off-by: Allen Bai --- README.md | 1 + src/providers/packet/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 31581bc1..5ea71b57 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ On CoreOS Container Linux, the supported providers and metadata are [somewhat di - Network Configs - Attributes - AFTERBURN_PACKET_HOSTNAME + - AFTERBURN_PACKET_PLAN - AFTERBURN_PACKET_IPV4_PUBLIC_0 - AFTERBURN_PACKET_IPV4_PRIVATE_0 - AFTERBURN_PACKET_IPV6_PUBLIC_0 diff --git a/src/providers/packet/mod.rs b/src/providers/packet/mod.rs index 3a42520e..68bcbbb0 100644 --- a/src/providers/packet/mod.rs +++ b/src/providers/packet/mod.rs @@ -144,6 +144,7 @@ impl PacketProvider { "PACKET_PHONE_HOME_URL".to_owned(), self.data.phone_home_url.clone(), )); + attrs.push(("PACKET_PLAN".to_owned(), self.data.plan.clone())); Ok(attrs) } From bce9fbea64d32b58f9d1d645dbf888efddd8d0ff Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Mon, 7 Oct 2019 10:50:57 -0400 Subject: [PATCH 06/12] providers/azure: Use vmSize instead of sku Addresses improvments suggested in the review and adds documentation in container-linux-legacy.md. Signed-off-by: Allen Bai --- README.md | 2 +- docs/container-linux-legacy.md | 5 +++++ src/providers/azure/mod.rs | 20 +++++++++----------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 5ea71b57..8a293ac3 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ On CoreOS Container Linux, the supported providers and metadata are [somewhat di - Attributes - AFTERBURN_AZURE_IPV4_DYNAMIC - AFTERBURN_AZURE_IPV4_VIRTUAL - - AFTERBURN_AZURE_SKU + - AFTERBURN_AZURE_VMSIZE - cloudstack-configdrive - SSH Keys - Attributes diff --git a/docs/container-linux-legacy.md b/docs/container-linux-legacy.md index 09638948..c86ccad0 100644 --- a/docs/container-linux-legacy.md +++ b/docs/container-linux-legacy.md @@ -17,6 +17,7 @@ On Container Linux, the supported cloud providers and their respective metadata - Attributes - COREOS_AZURE_IPV4_DYNAMIC - COREOS_AZURE_IPV4_VIRTUAL + - COREOS_AZURE_VMSIZE - cloudstack-configdrive - SSH Keys - Attributes @@ -59,6 +60,7 @@ On Container Linux, the supported cloud providers and their respective metadata - COREOS_EC2_IPV4_PUBLIC - COREOS_EC2_AVAILABILITY_ZONE - COREOS_EC2_INSTANCE_ID + - COREOS_EC2_INSTANCE_TYPE - COREOS_EC2_REGION - gce - SSH Keys @@ -66,6 +68,7 @@ On Container Linux, the supported cloud providers and their respective metadata - COREOS_GCE_HOSTNAME - COREOS_GCE_IP_EXTERNAL_0 - COREOS_GCE_IP_LOCAL_0 + - COREOS_GCE_MACHINE_TYPE - openstack-metadata - SSH Keys - Attributes @@ -73,11 +76,13 @@ On Container Linux, the supported cloud providers and their respective metadata - COREOS_OPENSTACK_IPV4_LOCAL - COREOS_OPENSTACK_IPV4_PUBLIC - COREOS_OPENSTACK_INSTANCE_ID + - COREOS_OPENSTACK_INSTANCE_TYPE - packet - SSH Keys - Network Configs - Attributes - COREOS_PACKET_HOSTNAME + - COREOS_PACKET_PLAN - COREOS_PACKET_IPV4_PUBLIC_0 - COREOS_PACKET_IPV4_PRIVATE_0 - COREOS_PACKET_IPV6_PUBLIC_0 diff --git a/src/providers/azure/mod.rs b/src/providers/azure/mod.rs index 769617a5..1a4b7eea 100644 --- a/src/providers/azure/mod.rs +++ b/src/providers/azure/mod.rs @@ -419,26 +419,26 @@ impl Azure { Ok(name) } - fn fetch_sku (&self) -> Result> { - const SKU_URL: &str = "metadata/instance/compute/sku?api-version=2017-08-01&format=text"; - let url = format!("{}/{}", Self::metadata_endpoint(), SKU_URL); + fn fetch_vmsize (&self) -> Result { + const VMSIZE_URL: &str = "metadata/instance/compute/vmSize?api-version=2017-08-01&format=text"; + let url = format!("{}/{}", Self::metadata_endpoint(), VMSIZE_URL); - let sku = retry::Client::try_new()? + let vmsize = retry::Client::try_new()? .header( HeaderName::from_static("metadata"), HeaderValue::from_static("true"), ) .get(retry::Raw, url) - .send() - .chain_err(|| "failed to get sku")?; - Ok(sku) + .send()? + .chain_err(|| "failed to get vmsize")?; + Ok(vmsize) } } impl MetadataProvider for Azure { fn attributes(&self) -> Result> { let attributes = self.get_attributes()?; - let sku = self.fetch_sku()?; + let vmsize = self.fetch_vmsize()?; let mut out = HashMap::with_capacity(3); if let Some(virtual_ipv4) = attributes.virtual_ipv4 { @@ -449,9 +449,7 @@ impl MetadataProvider for Azure { out.insert("AZURE_IPV4_DYNAMIC".to_string(), dynamic_ipv4.to_string()); } - if let Some(sku) = sku { - out.insert("AZURE_SKU".to_string(), sku.to_string()); - } + out.insert("AZURE_VMSIZE".to_string(), vmsize.to_string()); Ok(out) } From d2e0dcd640bc918e874c2c8c48e768b168b55770 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Mon, 7 Oct 2019 12:27:09 -0400 Subject: [PATCH 07/12] providers/azure: Add mock-test for vmSize fetching Signed-off-by: Allen Bai --- src/providers/azure/mock_tests.rs | 25 +++++++++++++++++++++++++ src/providers/azure/mod.rs | 13 ++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/providers/azure/mock_tests.rs b/src/providers/azure/mock_tests.rs index da332788..554cacff 100644 --- a/src/providers/azure/mock_tests.rs +++ b/src/providers/azure/mock_tests.rs @@ -113,3 +113,28 @@ fn test_hostname() { let hostname = r.unwrap(); assert_eq!(hostname, testname); } + +#[test] +fn test_vmsize() { + let m_version = mock_fab_version(); + let m_goalstate = mock_goalstate(); + + let testvmsize = "testvmsize"; + let endpoint = "/metadata/instance/compute/vmSize?api-version=2017-08-01&format=text"; + let m_vmsize = mockito::mock("GET", endpoint) + .match_header("Metadata", "true") + .with_body(testvmsize) + .with_status(200) + .create(); + + let provider = azure::Azure::try_new(); + let attributes = provider.unwrap().attributes().unwrap(); + let r = attributes.get("AZURE_VMSIZE"); + + m_version.assert(); + m_goalstate.assert(); + + m_vmsize.assert(); + let vmsize = r.unwrap(); + assert_eq!(vmsize, testvmsize); +} diff --git a/src/providers/azure/mod.rs b/src/providers/azure/mod.rs index 1a4b7eea..415b2574 100644 --- a/src/providers/azure/mod.rs +++ b/src/providers/azure/mod.rs @@ -17,7 +17,9 @@ mod crypto; use std::collections::HashMap; -use std::net::{IpAddr, SocketAddr}; +use std::net::IpAddr; +#[cfg(not(test))] +use std::net::SocketAddr; use openssh_keys::PublicKey; use reqwest::header::{HeaderName, HeaderValue}; @@ -355,6 +357,15 @@ impl Azure { Ok(ssh_pubkey) } + #[cfg(test)] + fn get_attributes(&self) -> Result { + Ok(Attributes{ + virtual_ipv4: Some(Azure::get_fabric_address()), + dynamic_ipv4: Some(Azure::get_fabric_address()), + }) + } + + #[cfg(not(test))] fn get_attributes(&self) -> Result { let endpoint = &self.goal_state.container.role_instance_list.role_instances[0] .configuration From f9761647f2d38bce46fcb740f159f572ac320e90 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Tue, 8 Oct 2019 09:44:30 -0400 Subject: [PATCH 08/12] providers/gcp: Add mock-test for attributes fetching Signed-off-by: Allen Bai --- src/providers/gcp/mock_tests.rs | 51 +++++++++++++++++++++++++++++++++ src/providers/gcp/mod.rs | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/providers/gcp/mock_tests.rs b/src/providers/gcp/mock_tests.rs index 21e10ef4..f94b8f8e 100644 --- a/src/providers/gcp/mock_tests.rs +++ b/src/providers/gcp/mock_tests.rs @@ -1,7 +1,13 @@ use crate::providers::gcp; use crate::providers::MetadataProvider; +use std::collections::HashMap; use mockito; +#[cfg(not(feature = "cl-legacy"))] +static ENV_PREFIX: &str = "GCP"; +#[cfg(feature = "cl-legacy")] +static ENV_PREFIX: &str = "GCE"; + #[test] fn basic_hostname() { let ep = "/instance/hostname"; @@ -27,3 +33,48 @@ fn basic_hostname() { mockito::reset(); provider.hostname().unwrap_err(); } + +#[test] +fn basic_attributes() { + let ep_hostname = "/instance/hostname"; + let hostname = "test-hostname"; + + let ep_ip_external = "/instance/network-interfaces/0/access-configs/0/external-ip"; + let ip_external = "test-ip-external"; + + let ep_ip_local = "/instance/network-interfaces/0/ip"; + let ip_local = "test-ip-local"; + + let ep_machine_type = "/instance/machine-type"; + let machine_type = "test-machine-type"; + + let mut attributes:HashMap = HashMap::new(); + attributes.insert(format!("{}_HOSTNAME", ENV_PREFIX), String::from(hostname)); + attributes.insert(format!("{}_IP_EXTERNAL_0", ENV_PREFIX), String::from(ip_external)); + attributes.insert(format!("{}_IP_LOCAL_0", ENV_PREFIX), String::from(ip_local)); + attributes.insert(format!("{}_MACHINE_TYPE", ENV_PREFIX), String::from(machine_type)); + + let mut provider = gcp::GcpProvider::try_new().unwrap(); + provider.client = provider.client.max_attempts(1); + + let _m = mockito::mock("GET", ep_hostname) + .with_status(200) + .with_body(hostname) + .create(); + let _m = mockito::mock("GET", ep_ip_external) + .with_status(200) + .with_body(ip_external) + .create(); + let _m = mockito::mock("GET", ep_ip_local) + .with_status(200) + .with_body(ip_local) + .create(); + let _m = mockito::mock("GET", ep_machine_type) + .with_status(200) + .with_body(machine_type) + .create(); + + let v = provider.attributes().unwrap(); + + assert_eq!(v, attributes); +} diff --git a/src/providers/gcp/mod.rs b/src/providers/gcp/mod.rs index 9f887828..3ee985d0 100644 --- a/src/providers/gcp/mod.rs +++ b/src/providers/gcp/mod.rs @@ -131,7 +131,7 @@ impl GcpProvider { impl MetadataProvider for GcpProvider { fn attributes(&self) -> Result> { - let mut out = HashMap::with_capacity(3); + let mut out = HashMap::with_capacity(4); let add_value = |map: &mut HashMap<_, _>, key: &str, name| -> Result<()> { let value: Option = self From eb7e920c26b9d52b5117bd7626dfd9132030e2b2 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Tue, 8 Oct 2019 10:39:56 -0400 Subject: [PATCH 09/12] providers/aws: Add mock-test for attributes fetching Signed-off-by: Allen Bai --- src/providers/aws/mock_tests.rs | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/providers/aws/mock_tests.rs b/src/providers/aws/mock_tests.rs index 6e694f9a..49907a93 100644 --- a/src/providers/aws/mock_tests.rs +++ b/src/providers/aws/mock_tests.rs @@ -1,6 +1,13 @@ use crate::errors::*; use crate::providers::aws; use mockito; +use std::collections::HashMap; +use crate::providers::MetadataProvider; + +#[cfg(not(feature = "cl-legacy"))] +static ENV_PREFIX: &str = "AWS"; +#[cfg(feature = "cl-legacy")] +static ENV_PREFIX: &str = "EC2"; #[test] fn test_aws_basic() { @@ -25,3 +32,85 @@ fn test_aws_basic() { let v = provider.fetch_ssh_keys().unwrap(); assert_eq!(v.len(), 0); } + +#[test] +fn test_attributes_fetching() { + let ep_instance_id = "/meta-data/instance-id"; + let instance_id = "test-instance-id"; + + let ep_instance_type = "/meta-data/instance-type"; + let instance_type = "test-instance-type"; + + let ep_ipv4_local = "/meta-data/local-ipv4"; + let ipv4_local = "test-ipv4-local"; + + let ep_ipv4_public = "/meta-data/public-ipv4"; + let ipv4_public = "test-ipv4-public"; + + let ep_availability_zone = "/meta-data/placement/availability-zone"; + let availability_zone = "test-availability-zone"; + + let ep_hostname = "/meta-data/hostname"; + let hostname = "test-hostname"; + + let ep_public_hostname = "/meta-data/public-hostname"; + let public_hostname = "test-public-hostname"; + + let ep_region = "/dynamic/instance-identity/document"; + let instance_id_doc = "{\"region\": \"test-region\"}"; + let region = "test-region"; + + let mut attributes:HashMap = HashMap::new(); + attributes.insert(format!("{}_INSTANCE_ID", ENV_PREFIX), String::from(instance_id)); + attributes.insert(format!("{}_INSTANCE_TYPE", ENV_PREFIX), String::from(instance_type)); + attributes.insert(format!("{}_IPV4_LOCAL", ENV_PREFIX), String::from(ipv4_local)); + attributes.insert(format!("{}_IPV4_PUBLIC", ENV_PREFIX), String::from(ipv4_public)); + attributes.insert(format!("{}_AVAILABILITY_ZONE", ENV_PREFIX), String::from(availability_zone)); + attributes.insert(format!("{}_HOSTNAME", ENV_PREFIX), String::from(hostname)); + attributes.insert(format!("{}_PUBLIC_HOSTNAME", ENV_PREFIX), String::from(public_hostname)); + attributes.insert(format!("{}_REGION", ENV_PREFIX), String::from(region)); + + let client = crate::retry::Client::try_new() + .chain_err(|| "failed to create http client") + .unwrap() + .max_attempts(1) + .return_on_404(true); + let provider = aws::AwsProvider { client }; + + let _m = mockito::mock("GET", ep_instance_id) + .with_status(200) + .with_body(instance_id) + .create(); + let _m = mockito::mock("GET", ep_instance_type) + .with_status(200) + .with_body(instance_type) + .create(); + let _m = mockito::mock("GET", ep_ipv4_local) + .with_status(200) + .with_body(ipv4_local) + .create(); + let _m = mockito::mock("GET", ep_ipv4_public) + .with_status(200) + .with_body(ipv4_public) + .create(); + let _m = mockito::mock("GET", ep_availability_zone) + .with_status(200) + .with_body(availability_zone) + .create(); + let _m = mockito::mock("GET", ep_hostname) + .with_status(200) + .with_body(hostname) + .create(); + let _m = mockito::mock("GET", ep_public_hostname) + .with_status(200) + .with_body(public_hostname) + .create(); + let _m = mockito::mock("GET", ep_region) + .with_status(200) + .with_body(instance_id_doc) + .create(); + + let v = provider.attributes().unwrap(); + + assert_eq!(v, attributes); +} \ No newline at end of file From 0fe9934f98ed3967793f526abd3ebe838ae88f08 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Tue, 8 Oct 2019 11:56:03 -0400 Subject: [PATCH 10/12] providers/packet: Add mock-test for attributes fetching Signed-off-by: Allen Bai --- src/providers/aws/mock_tests.rs | 2 +- src/providers/packet/mock_tests.rs | 39 ++++++++++++++++++++++++++++++ src/providers/packet/mod.rs | 17 +++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/providers/aws/mock_tests.rs b/src/providers/aws/mock_tests.rs index 49907a93..4b21fa6c 100644 --- a/src/providers/aws/mock_tests.rs +++ b/src/providers/aws/mock_tests.rs @@ -34,7 +34,7 @@ fn test_aws_basic() { } #[test] -fn test_attributes_fetching() { +fn test_aws_attributes() { let ep_instance_id = "/meta-data/instance-id"; let instance_id = "test-instance-id"; diff --git a/src/providers/packet/mock_tests.rs b/src/providers/packet/mock_tests.rs index 5a07ef20..42e5b8c9 100644 --- a/src/providers/packet/mock_tests.rs +++ b/src/providers/packet/mock_tests.rs @@ -1,5 +1,6 @@ use crate::providers::{packet, MetadataProvider}; use mockito::{self, Matcher}; +use std::collections::HashMap; #[test] fn test_boot_checkin() { @@ -34,3 +35,41 @@ fn test_boot_checkin() { mock.assert(); r.unwrap(); } + +#[test] +fn test_packet_attributes() { + let metadata = "{ + \"id\": \"test-id\", + \"hostname\": \"test-hostname\", + \"iqn\": \"test-iqn\", + \"plan\": \"test-plan\", + \"facility\": \"test-facility\", + \"tags\": [], + \"ssh_keys\": [], + \"network\": { + \"interfaces\": [], + \"addresses\": [], + \"bonding\": { \"mode\": 0 } + }, + \"phone_home_url\": \"test-url\" + }"; + + let hostname = "test-hostname"; + let phone_home_url = "test-url"; + let plan = "test-plan"; + + let mut attributes:HashMap = HashMap::new(); + attributes.insert(format!("PACKET_HOSTNAME"), String::from(hostname)); + attributes.insert(format!("PACKET_PHONE_HOME_URL"), String::from(phone_home_url)); + attributes.insert(format!("PACKET_PLAN"), String::from(plan)); + + let _m = mockito::mock("GET", "/metadata") + .with_status(200) + .with_body(metadata) + .create(); + + let provider = packet::PacketProvider::try_new().unwrap(); + let v = provider.attributes().unwrap(); + + assert_eq!(v, attributes); +} \ No newline at end of file diff --git a/src/providers/packet/mod.rs b/src/providers/packet/mod.rs index 68bcbbb0..0341e9ac 100644 --- a/src/providers/packet/mod.rs +++ b/src/providers/packet/mod.rs @@ -87,6 +87,23 @@ pub struct PacketProvider { } impl PacketProvider { + #[cfg(test)] + pub fn try_new() -> Result { + let client = retry::Client::try_new()?; + let url = mockito::server_url(); + + let data: PacketData = client + .get( + retry::Json, + format!("{}/metadata", url), + ) + .send()? + .ok_or("not found")?; + + Ok(PacketProvider { data }) + } + + #[cfg(not(test))] pub fn try_new() -> Result { let client = retry::Client::try_new()?; From cfffae46d3fe98efe994c4985f696174ec7c2fd9 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Wed, 9 Oct 2019 11:24:41 -0400 Subject: [PATCH 11/12] providers/tests: address review comments and cleanup tests setup Signed-off-by: Allen Bai --- src/providers/aws/mock_tests.rs | 99 ++++++++++-------------------- src/providers/azure/mod.rs | 4 +- src/providers/gcp/mock_tests.rs | 69 +++++++++------------ src/providers/packet/mock_tests.rs | 40 ++++++------ 4 files changed, 86 insertions(+), 126 deletions(-) diff --git a/src/providers/aws/mock_tests.rs b/src/providers/aws/mock_tests.rs index 4b21fa6c..380fea43 100644 --- a/src/providers/aws/mock_tests.rs +++ b/src/providers/aws/mock_tests.rs @@ -1,14 +1,8 @@ use crate::errors::*; use crate::providers::aws; use mockito; -use std::collections::HashMap; use crate::providers::MetadataProvider; -#[cfg(not(feature = "cl-legacy"))] -static ENV_PREFIX: &str = "AWS"; -#[cfg(feature = "cl-legacy")] -static ENV_PREFIX: &str = "EC2"; - #[test] fn test_aws_basic() { let ep = "/meta-data/public-keys"; @@ -35,40 +29,46 @@ fn test_aws_basic() { #[test] fn test_aws_attributes() { - let ep_instance_id = "/meta-data/instance-id"; let instance_id = "test-instance-id"; - - let ep_instance_type = "/meta-data/instance-type"; let instance_type = "test-instance-type"; - - let ep_ipv4_local = "/meta-data/local-ipv4"; let ipv4_local = "test-ipv4-local"; - - let ep_ipv4_public = "/meta-data/public-ipv4"; let ipv4_public = "test-ipv4-public"; - - let ep_availability_zone = "/meta-data/placement/availability-zone"; let availability_zone = "test-availability-zone"; - - let ep_hostname = "/meta-data/hostname"; let hostname = "test-hostname"; - - let ep_public_hostname = "/meta-data/public-hostname"; let public_hostname = "test-public-hostname"; - - let ep_region = "/dynamic/instance-identity/document"; - let instance_id_doc = "{\"region\": \"test-region\"}"; + let instance_id_doc = r#"{"region": "test-region"}"#; let region = "test-region"; - let mut attributes:HashMap = HashMap::new(); - attributes.insert(format!("{}_INSTANCE_ID", ENV_PREFIX), String::from(instance_id)); - attributes.insert(format!("{}_INSTANCE_TYPE", ENV_PREFIX), String::from(instance_type)); - attributes.insert(format!("{}_IPV4_LOCAL", ENV_PREFIX), String::from(ipv4_local)); - attributes.insert(format!("{}_IPV4_PUBLIC", ENV_PREFIX), String::from(ipv4_public)); - attributes.insert(format!("{}_AVAILABILITY_ZONE", ENV_PREFIX), String::from(availability_zone)); - attributes.insert(format!("{}_HOSTNAME", ENV_PREFIX), String::from(hostname)); - attributes.insert(format!("{}_PUBLIC_HOSTNAME", ENV_PREFIX), String::from(public_hostname)); - attributes.insert(format!("{}_REGION", ENV_PREFIX), String::from(region)); + let endpoints = 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/placement/availability-zone" => availability_zone, + "/meta-data/hostname" => hostname, + "/meta-data/public-hostname" => public_hostname, + "/dynamic/instance-identity/document" => instance_id_doc, + }; + + let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints { + let m = mockito::mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); + mocks.push(m); + } + + let attributes = maplit::hashmap! { + format!("{}_INSTANCE_ID", aws::ENV_PREFIX) => String::from(instance_id), + format!("{}_INSTANCE_TYPE", aws::ENV_PREFIX) => String::from(instance_type), + format!("{}_IPV4_LOCAL", aws::ENV_PREFIX) => String::from(ipv4_local), + format!("{}_IPV4_PUBLIC", aws::ENV_PREFIX) => String::from(ipv4_public), + format!("{}_AVAILABILITY_ZONE", aws::ENV_PREFIX) => String::from(availability_zone), + format!("{}_HOSTNAME", aws::ENV_PREFIX) => String::from(hostname), + format!("{}_PUBLIC_HOSTNAME", aws::ENV_PREFIX) => String::from(public_hostname), + format!("{}_REGION", aws::ENV_PREFIX) => String::from(region), + }; let client = crate::retry::Client::try_new() .chain_err(|| "failed to create http client") @@ -77,40 +77,9 @@ fn test_aws_attributes() { .return_on_404(true); let provider = aws::AwsProvider { client }; - let _m = mockito::mock("GET", ep_instance_id) - .with_status(200) - .with_body(instance_id) - .create(); - let _m = mockito::mock("GET", ep_instance_type) - .with_status(200) - .with_body(instance_type) - .create(); - let _m = mockito::mock("GET", ep_ipv4_local) - .with_status(200) - .with_body(ipv4_local) - .create(); - let _m = mockito::mock("GET", ep_ipv4_public) - .with_status(200) - .with_body(ipv4_public) - .create(); - let _m = mockito::mock("GET", ep_availability_zone) - .with_status(200) - .with_body(availability_zone) - .create(); - let _m = mockito::mock("GET", ep_hostname) - .with_status(200) - .with_body(hostname) - .create(); - let _m = mockito::mock("GET", ep_public_hostname) - .with_status(200) - .with_body(public_hostname) - .create(); - let _m = mockito::mock("GET", ep_region) - .with_status(200) - .with_body(instance_id_doc) - .create(); - let v = provider.attributes().unwrap(); - assert_eq!(v, attributes); + + mockito::reset(); + provider.attributes().unwrap_err(); } \ No newline at end of file diff --git a/src/providers/azure/mod.rs b/src/providers/azure/mod.rs index 415b2574..0c70e691 100644 --- a/src/providers/azure/mod.rs +++ b/src/providers/azure/mod.rs @@ -18,8 +18,6 @@ mod crypto; use std::collections::HashMap; use std::net::IpAddr; -#[cfg(not(test))] -use std::net::SocketAddr; use openssh_keys::PublicKey; use reqwest::header::{HeaderName, HeaderValue}; @@ -367,6 +365,8 @@ impl Azure { #[cfg(not(test))] fn get_attributes(&self) -> Result { + use std::net::SocketAddr; + let endpoint = &self.goal_state.container.role_instance_list.role_instances[0] .configuration .shared_config; diff --git a/src/providers/gcp/mock_tests.rs b/src/providers/gcp/mock_tests.rs index f94b8f8e..d9328815 100644 --- a/src/providers/gcp/mock_tests.rs +++ b/src/providers/gcp/mock_tests.rs @@ -1,13 +1,7 @@ use crate::providers::gcp; use crate::providers::MetadataProvider; -use std::collections::HashMap; use mockito; -#[cfg(not(feature = "cl-legacy"))] -static ENV_PREFIX: &str = "GCP"; -#[cfg(feature = "cl-legacy")] -static ENV_PREFIX: &str = "GCE"; - #[test] fn basic_hostname() { let ep = "/instance/hostname"; @@ -36,45 +30,42 @@ fn basic_hostname() { #[test] fn basic_attributes() { - let ep_hostname = "/instance/hostname"; let hostname = "test-hostname"; - - let ep_ip_external = "/instance/network-interfaces/0/access-configs/0/external-ip"; let ip_external = "test-ip-external"; - - let ep_ip_local = "/instance/network-interfaces/0/ip"; let ip_local = "test-ip-local"; - - let ep_machine_type = "/instance/machine-type"; let machine_type = "test-machine-type"; - let mut attributes:HashMap = HashMap::new(); - attributes.insert(format!("{}_HOSTNAME", ENV_PREFIX), String::from(hostname)); - attributes.insert(format!("{}_IP_EXTERNAL_0", ENV_PREFIX), String::from(ip_external)); - attributes.insert(format!("{}_IP_LOCAL_0", ENV_PREFIX), String::from(ip_local)); - attributes.insert(format!("{}_MACHINE_TYPE", ENV_PREFIX), String::from(machine_type)); - - let mut provider = gcp::GcpProvider::try_new().unwrap(); - provider.client = provider.client.max_attempts(1); - - let _m = mockito::mock("GET", ep_hostname) - .with_status(200) - .with_body(hostname) - .create(); - let _m = mockito::mock("GET", ep_ip_external) - .with_status(200) - .with_body(ip_external) - .create(); - let _m = mockito::mock("GET", ep_ip_local) - .with_status(200) - .with_body(ip_local) - .create(); - let _m = mockito::mock("GET", ep_machine_type) - .with_status(200) - .with_body(machine_type) - .create(); + 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, + }; + let mut mocks = Vec::with_capacity(endpoints.len()); + for (endpoint, body) in endpoints { + let m = mockito::mock("GET", endpoint) + .with_status(200) + .with_body(body) + .create(); + mocks.push(m); + } + + let attributes = maplit::hashmap! { + format!("{}_HOSTNAME", gcp::ENV_PREFIX) => String::from(hostname), + format!("{}_IP_EXTERNAL_0", gcp::ENV_PREFIX) => String::from(ip_external), + format!("{}_IP_LOCAL_0", gcp::ENV_PREFIX) => String::from(ip_local), + format!("{}_MACHINE_TYPE", gcp::ENV_PREFIX) => String::from(machine_type), + }; + + let client = crate::retry::Client::try_new() + .unwrap() + .max_attempts(1) + .return_on_404(true); + let provider = gcp::GcpProvider { client }; let v = provider.attributes().unwrap(); - assert_eq!(v, attributes); + + mockito::reset(); + provider.attributes().unwrap_err(); } diff --git a/src/providers/packet/mock_tests.rs b/src/providers/packet/mock_tests.rs index 42e5b8c9..dce47a6f 100644 --- a/src/providers/packet/mock_tests.rs +++ b/src/providers/packet/mock_tests.rs @@ -1,6 +1,5 @@ use crate::providers::{packet, MetadataProvider}; use mockito::{self, Matcher}; -use std::collections::HashMap; #[test] fn test_boot_checkin() { @@ -38,30 +37,31 @@ fn test_boot_checkin() { #[test] fn test_packet_attributes() { - let metadata = "{ - \"id\": \"test-id\", - \"hostname\": \"test-hostname\", - \"iqn\": \"test-iqn\", - \"plan\": \"test-plan\", - \"facility\": \"test-facility\", - \"tags\": [], - \"ssh_keys\": [], - \"network\": { - \"interfaces\": [], - \"addresses\": [], - \"bonding\": { \"mode\": 0 } + let metadata = r#"{ + "id": "test-id", + "hostname": "test-hostname", + "iqn": "test-iqn", + "plan": "test-plan", + "facility": "test-facility", + "tags": [], + "ssh_keys": [], + "network": { + "interfaces": [], + "addresses": [], + "bonding": { "mode": 0 } }, - \"phone_home_url\": \"test-url\" - }"; + "phone_home_url": "test-url" + }"#; let hostname = "test-hostname"; let phone_home_url = "test-url"; let plan = "test-plan"; - let mut attributes:HashMap = HashMap::new(); - attributes.insert(format!("PACKET_HOSTNAME"), String::from(hostname)); - attributes.insert(format!("PACKET_PHONE_HOME_URL"), String::from(phone_home_url)); - attributes.insert(format!("PACKET_PLAN"), String::from(plan)); + let attributes = maplit::hashmap! { + format!("PACKET_HOSTNAME") => String::from(hostname), + format!("PACKET_PHONE_HOME_URL") => String::from(phone_home_url), + format!("PACKET_PLAN") => String::from(plan), + }; let _m = mockito::mock("GET", "/metadata") .with_status(200) @@ -72,4 +72,4 @@ fn test_packet_attributes() { let v = provider.attributes().unwrap(); assert_eq!(v, attributes); -} \ No newline at end of file +} From 76753a5b8723818412c434b65ee632f7a8e94b21 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Thu, 10 Oct 2019 10:45:10 -0400 Subject: [PATCH 12/12] providers/mock-tests: add mockito::reset and minor changes Signed-off-by: Allen Bai --- src/providers/aws/mock_tests.rs | 19 +++++++++++-------- src/providers/azure/mock_tests.rs | 9 +++++++++ src/providers/gcp/mock_tests.rs | 8 ++++---- src/providers/packet/mock_tests.rs | 16 +++++++++------- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/providers/aws/mock_tests.rs b/src/providers/aws/mock_tests.rs index 380fea43..d09837c6 100644 --- a/src/providers/aws/mock_tests.rs +++ b/src/providers/aws/mock_tests.rs @@ -25,6 +25,9 @@ fn test_aws_basic() { let _m = mockito::mock("GET", ep).with_status(404).create(); let v = provider.fetch_ssh_keys().unwrap(); assert_eq!(v.len(), 0); + + mockito::reset(); + provider.fetch_ssh_keys().unwrap_err(); } #[test] @@ -60,14 +63,14 @@ fn test_aws_attributes() { } let attributes = maplit::hashmap! { - format!("{}_INSTANCE_ID", aws::ENV_PREFIX) => String::from(instance_id), - format!("{}_INSTANCE_TYPE", aws::ENV_PREFIX) => String::from(instance_type), - format!("{}_IPV4_LOCAL", aws::ENV_PREFIX) => String::from(ipv4_local), - format!("{}_IPV4_PUBLIC", aws::ENV_PREFIX) => String::from(ipv4_public), - format!("{}_AVAILABILITY_ZONE", aws::ENV_PREFIX) => String::from(availability_zone), - format!("{}_HOSTNAME", aws::ENV_PREFIX) => String::from(hostname), - format!("{}_PUBLIC_HOSTNAME", aws::ENV_PREFIX) => String::from(public_hostname), - format!("{}_REGION", aws::ENV_PREFIX) => String::from(region), + format!("{}_INSTANCE_ID", aws::ENV_PREFIX) => instance_id.to_string(), + format!("{}_INSTANCE_TYPE", aws::ENV_PREFIX) => instance_type.to_string(), + format!("{}_IPV4_LOCAL", aws::ENV_PREFIX) => ipv4_local.to_string(), + format!("{}_IPV4_PUBLIC", aws::ENV_PREFIX) => ipv4_public.to_string(), + format!("{}_AVAILABILITY_ZONE", aws::ENV_PREFIX) => availability_zone.to_string(), + format!("{}_HOSTNAME", aws::ENV_PREFIX) => hostname.to_string(), + format!("{}_PUBLIC_HOSTNAME", aws::ENV_PREFIX) => public_hostname.to_string(), + format!("{}_REGION", aws::ENV_PREFIX) => region.to_string(), }; let client = crate::retry::Client::try_new() diff --git a/src/providers/azure/mock_tests.rs b/src/providers/azure/mock_tests.rs index 554cacff..b3c3f153 100644 --- a/src/providers/azure/mock_tests.rs +++ b/src/providers/azure/mock_tests.rs @@ -88,6 +88,9 @@ fn test_boot_checkin() { m_goalstate.assert(); m_health.assert(); r.unwrap(); + + mockito::reset(); + azure::Azure::try_new().unwrap_err(); } #[test] @@ -112,6 +115,9 @@ fn test_hostname() { m_hostname.assert(); let hostname = r.unwrap(); assert_eq!(hostname, testname); + + mockito::reset(); + azure::Azure::try_new().unwrap_err(); } #[test] @@ -137,4 +143,7 @@ fn test_vmsize() { m_vmsize.assert(); let vmsize = r.unwrap(); assert_eq!(vmsize, testvmsize); + + mockito::reset(); + azure::Azure::try_new().unwrap_err(); } diff --git a/src/providers/gcp/mock_tests.rs b/src/providers/gcp/mock_tests.rs index d9328815..7c3b5f27 100644 --- a/src/providers/gcp/mock_tests.rs +++ b/src/providers/gcp/mock_tests.rs @@ -51,10 +51,10 @@ fn basic_attributes() { } let attributes = maplit::hashmap! { - format!("{}_HOSTNAME", gcp::ENV_PREFIX) => String::from(hostname), - format!("{}_IP_EXTERNAL_0", gcp::ENV_PREFIX) => String::from(ip_external), - format!("{}_IP_LOCAL_0", gcp::ENV_PREFIX) => String::from(ip_local), - format!("{}_MACHINE_TYPE", gcp::ENV_PREFIX) => String::from(machine_type), + format!("{}_HOSTNAME", gcp::ENV_PREFIX) => hostname.to_string(), + format!("{}_IP_EXTERNAL_0", gcp::ENV_PREFIX) => ip_external.to_string(), + format!("{}_IP_LOCAL_0", gcp::ENV_PREFIX) => ip_local.to_string(), + format!("{}_MACHINE_TYPE", gcp::ENV_PREFIX) => machine_type.to_string(), }; let client = crate::retry::Client::try_new() diff --git a/src/providers/packet/mock_tests.rs b/src/providers/packet/mock_tests.rs index dce47a6f..eeb76d92 100644 --- a/src/providers/packet/mock_tests.rs +++ b/src/providers/packet/mock_tests.rs @@ -33,6 +33,9 @@ fn test_boot_checkin() { let r = provider.boot_checkin(); mock.assert(); r.unwrap(); + + mockito::reset(); + provider.boot_checkin().unwrap_err(); } #[test] @@ -53,14 +56,10 @@ fn test_packet_attributes() { "phone_home_url": "test-url" }"#; - let hostname = "test-hostname"; - let phone_home_url = "test-url"; - let plan = "test-plan"; - let attributes = maplit::hashmap! { - format!("PACKET_HOSTNAME") => String::from(hostname), - format!("PACKET_PHONE_HOME_URL") => String::from(phone_home_url), - format!("PACKET_PLAN") => String::from(plan), + "PACKET_HOSTNAME".to_string() => "test-hostname".to_string(), + "PACKET_PHONE_HOME_URL".to_string() => "test-url".to_string(), + "PACKET_PLAN".to_string() => "test-plan".to_string(), }; let _m = mockito::mock("GET", "/metadata") @@ -72,4 +71,7 @@ fn test_packet_attributes() { let v = provider.attributes().unwrap(); assert_eq!(v, attributes); + + mockito::reset(); + packet::PacketProvider::try_new().unwrap_err(); }