diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-5.6.0.ebuild b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-5.6.0-r1.ebuild similarity index 100% rename from sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-5.6.0.ebuild rename to sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-5.6.0-r1.ebuild diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-9999.ebuild b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-9999.ebuild index 44ccd17170..02247d4006 100644 --- a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-9999.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/afterburn-9999.ebuild @@ -367,6 +367,10 @@ PATCHES=( "${FILESDIR}"/0001-Revert-remove-cl-legacy-feature.patch "${FILESDIR}"/0002-util-cmdline-Handle-the-cmdline-flags-as-list-of-sup.patch "${FILESDIR}"/0003-Cargo-reduce-binary-size-for-release-profile.patch + # NOTE: For the next Afterburn upgrade, those two following patches can be dropped as they are + # already upstreamed. + "${FILESDIR}"/0004-providers-hetzner-fix-duplicate-attribute-prefix.patch + "${FILESDIR}"/0005-providers-hetzner-private-ipv4-addresses-in-attribut.patch ) src_unpack() { diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0004-providers-hetzner-fix-duplicate-attribute-prefix.patch b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0004-providers-hetzner-fix-duplicate-attribute-prefix.patch new file mode 100644 index 0000000000..4d782e71d6 --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0004-providers-hetzner-fix-duplicate-attribute-prefix.patch @@ -0,0 +1,74 @@ +From 6effcd345229da6b12d1206681f58e63220c534a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Julian=20T=C3=B6lle?= +Date: Tue, 4 Jun 2024 22:21:45 +0200 +Subject: [PATCH] providers/hetzner: fix duplicate attribute prefix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The attributes generated for the hetzner provider had a duplicate +prefix: + + AFTERBURN_AFTERBURN_HETZNER_HOSTNAME=flatcar-test + +Afterburn already adds the prefix itself in src/providers/mod.rs +`MetadataProvider.write_attributes()`, so the additional prefix added in +the hetzner provider was unnecessary. + +Signed-off-by: Julian Tölle +--- + src/providers/hetzner/mock_tests.rs | 10 +++++----- + src/providers/hetzner/mod.rs | 10 +++++----- + 3 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/src/providers/hetzner/mock_tests.rs b/src/providers/hetzner/mock_tests.rs +index 94d52a6..79a1662 100644 +--- a/src/providers/hetzner/mock_tests.rs ++++ b/src/providers/hetzner/mock_tests.rs +@@ -35,11 +35,11 @@ vendor_data: "blah blah blah""# + ); + + let expected = maplit::hashmap! { +- "AFTERBURN_HETZNER_AVAILABILITY_ZONE".to_string() => availability_zone.to_string(), +- "AFTERBURN_HETZNER_HOSTNAME".to_string() => hostname.to_string(), +- "AFTERBURN_HETZNER_INSTANCE_ID".to_string() => instance_id.to_string(), +- "AFTERBURN_HETZNER_PUBLIC_IPV4".to_string() => public_ipv4.to_string(), +- "AFTERBURN_HETZNER_REGION".to_string() => region.to_string(), ++ "HETZNER_AVAILABILITY_ZONE".to_string() => availability_zone.to_string(), ++ "HETZNER_HOSTNAME".to_string() => hostname.to_string(), ++ "HETZNER_INSTANCE_ID".to_string() => instance_id.to_string(), ++ "HETZNER_PUBLIC_IPV4".to_string() => public_ipv4.to_string(), ++ "HETZNER_REGION".to_string() => region.to_string(), + }; + + // Fail on not found +diff --git a/src/providers/hetzner/mod.rs b/src/providers/hetzner/mod.rs +index 5a575f0..58f9846 100644 +--- a/src/providers/hetzner/mod.rs ++++ b/src/providers/hetzner/mod.rs +@@ -112,17 +112,17 @@ impl From for HashMap { + + add_value( + &mut out, +- "AFTERBURN_HETZNER_AVAILABILITY_ZONE", ++ "HETZNER_AVAILABILITY_ZONE", + meta.availability_zone, + ); +- add_value(&mut out, "AFTERBURN_HETZNER_HOSTNAME", meta.hostname); ++ add_value(&mut out, "HETZNER_HOSTNAME", meta.hostname); + add_value( + &mut out, +- "AFTERBURN_HETZNER_INSTANCE_ID", ++ "HETZNER_INSTANCE_ID", + meta.instance_id.map(|i| i.to_string()), + ); +- add_value(&mut out, "AFTERBURN_HETZNER_PUBLIC_IPV4", meta.public_ipv4); +- add_value(&mut out, "AFTERBURN_HETZNER_REGION", meta.region); ++ add_value(&mut out, "HETZNER_PUBLIC_IPV4", meta.public_ipv4); ++ add_value(&mut out, "HETZNER_REGION", meta.region); + + out + } +-- +2.44.2 + diff --git a/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0005-providers-hetzner-private-ipv4-addresses-in-attribut.patch b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0005-providers-hetzner-private-ipv4-addresses-in-attribut.patch new file mode 100644 index 0000000000..3dece4e868 --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/coreos-base/afterburn/files/0005-providers-hetzner-private-ipv4-addresses-in-attribut.patch @@ -0,0 +1,262 @@ +From 0de46d6282d270004fa19c8981cbbb258afc4ffd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Julian=20T=C3=B6lle?= +Date: Sun, 21 Jul 2024 15:33:08 +0200 +Subject: [PATCH] providers/hetzner: private ipv4 addresses in attributes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds new attributes `AFTERBURN_HETZNER_PRIVATE_IPV4_*` set to the +servers IPv4 addresses in private networks. + +This is useful for e.g. discovery of etcd members that should +communicate over the private network. + +Signed-off-by: Julian Tölle +--- + src/providers/hetzner/mock_tests.rs | 49 +++++++++++++--- + src/providers/hetzner/mod.rs | 86 ++++++++++++++++++++++++----- + 4 files changed, 115 insertions(+), 22 deletions(-) + +diff --git a/src/providers/hetzner/mock_tests.rs b/src/providers/hetzner/mock_tests.rs +index 79a1662..443c702 100644 +--- a/src/providers/hetzner/mock_tests.rs ++++ b/src/providers/hetzner/mock_tests.rs +@@ -14,7 +14,8 @@ fn setup() -> (mockito::ServerGuard, HetznerProvider) { + + #[test] + fn test_attributes() { +- let endpoint = "/hetzner/v1/metadata"; ++ let endpoint_metadata = "/hetzner/v1/metadata"; ++ let endpoint_networks = "/hetzner/v1/metadata/private-networks"; + let (mut server, provider) = setup(); + + let availability_zone = "fsn1-dc14"; +@@ -23,7 +24,7 @@ fn test_attributes() { + let public_ipv4 = "192.0.2.10"; + let region = "eu-central"; + +- let body = format!( ++ let body_metadata = format!( + r#"availability-zone: {availability_zone} + hostname: {hostname} + instance-id: {instance_id} +@@ -34,30 +35,60 @@ public-keys: [] + vendor_data: "blah blah blah""# + ); + ++ let ip_0 = "10.0.0.2"; ++ let ip_1 = "10.128.0.2"; ++ ++ let body_networks = format!( ++ r#"- ip: {ip_0} ++- ip: {ip_1}"# ++ ); ++ + let expected = maplit::hashmap! { + "HETZNER_AVAILABILITY_ZONE".to_string() => availability_zone.to_string(), + "HETZNER_HOSTNAME".to_string() => hostname.to_string(), + "HETZNER_INSTANCE_ID".to_string() => instance_id.to_string(), + "HETZNER_PUBLIC_IPV4".to_string() => public_ipv4.to_string(), + "HETZNER_REGION".to_string() => region.to_string(), ++ "HETZNER_PRIVATE_IPV4_0".to_string() => ip_0.to_string(), ++ "HETZNER_PRIVATE_IPV4_1".to_string() => ip_1.to_string(), + }; + + // Fail on not found + provider.attributes().unwrap_err(); + +- // Fail on internal server errors +- let mock = server.mock("GET", endpoint).with_status(503).create(); ++ // Fail on internal server errors (metadata endpoint) ++ let mock_metadata = server ++ .mock("GET", endpoint_metadata) ++ .with_status(503) ++ .create(); + provider.attributes().unwrap_err(); +- mock.assert(); ++ mock_metadata.assert(); ++ ++ let mock_metadata = server ++ .mock("GET", endpoint_metadata) ++ .with_status(200) ++ .with_body(body_metadata) ++ .expect(2) // Once for the private-networks error test and once to compare the result ++ .create(); ++ ++ // Fail on internal server errors (networks endpoint) ++ let mock_networks = server ++ .mock("GET", endpoint_networks) ++ .with_status(503) ++ .create(); ++ provider.attributes().unwrap_err(); ++ mock_networks.assert(); + + // Fetch metadata +- let mock = server +- .mock("GET", endpoint) ++ let mock_networks = server ++ .mock("GET", endpoint_networks) + .with_status(200) +- .with_body(body) ++ .with_body(body_networks) + .create(); ++ + let actual = provider.attributes().unwrap(); +- mock.assert(); ++ mock_metadata.assert(); ++ mock_networks.assert(); + assert_eq!(actual, expected); + } + +diff --git a/src/providers/hetzner/mod.rs b/src/providers/hetzner/mod.rs +index 58f9846..6bb1d6e 100644 +--- a/src/providers/hetzner/mod.rs ++++ b/src/providers/hetzner/mod.rs +@@ -50,14 +50,24 @@ impl HetznerProvider { + } + + impl MetadataProvider for HetznerProvider { +- fn attributes(&self) -> Result> { +- let meta: HetznerMetadata = self ++ fn attributes(&self) -> Result> { ++ let metadata: Metadata = self + .client + .get(retry::Yaml, HETZNER_METADATA_BASE_URL.to_string()) + .send()? + .unwrap(); + +- Ok(meta.into()) ++ let private_networks: Vec = self ++ .client ++ .get(retry::Yaml, Self::endpoint_for("private-networks")) ++ .send()? ++ .unwrap(); ++ ++ Ok(Attributes { ++ metadata, ++ private_networks, ++ } ++ .into()) + } + + fn hostname(&self) -> Result> { +@@ -90,9 +100,14 @@ impl MetadataProvider for HetznerProvider { + } + } + ++#[derive(Debug, Deserialize)] ++struct PrivateNetwork { ++ ip: Option, ++} ++ + #[derive(Debug, Deserialize)] + #[serde(rename_all = "kebab-case")] +-struct HetznerMetadata { ++struct Metadata { + hostname: Option, + instance_id: Option, + public_ipv4: Option, +@@ -100,8 +115,13 @@ struct HetznerMetadata { + region: Option, + } + +-impl From for HashMap { +- fn from(meta: HetznerMetadata) -> Self { ++struct Attributes { ++ metadata: Metadata, ++ private_networks: Vec, ++} ++ ++impl From for HashMap { ++ fn from(attributes: Attributes) -> Self { + let mut out = HashMap::with_capacity(5); + + let add_value = |map: &mut HashMap<_, _>, key: &str, value: Option| { +@@ -113,16 +133,28 @@ impl From for HashMap { + add_value( + &mut out, + "HETZNER_AVAILABILITY_ZONE", +- meta.availability_zone, ++ attributes.metadata.availability_zone, + ); +- add_value(&mut out, "HETZNER_HOSTNAME", meta.hostname); ++ add_value(&mut out, "HETZNER_HOSTNAME", attributes.metadata.hostname); + add_value( + &mut out, + "HETZNER_INSTANCE_ID", +- meta.instance_id.map(|i| i.to_string()), ++ attributes.metadata.instance_id.map(|i| i.to_string()), ++ ); ++ add_value( ++ &mut out, ++ "HETZNER_PUBLIC_IPV4", ++ attributes.metadata.public_ipv4, + ); +- add_value(&mut out, "HETZNER_PUBLIC_IPV4", meta.public_ipv4); +- add_value(&mut out, "HETZNER_REGION", meta.region); ++ add_value(&mut out, "HETZNER_REGION", attributes.metadata.region); ++ ++ for (i, a) in attributes.private_networks.iter().enumerate() { ++ add_value( ++ &mut out, ++ format!("HETZNER_PRIVATE_IPV4_{i}").as_str(), ++ a.ip.clone(), ++ ); ++ } + + out + } +@@ -130,7 +162,7 @@ impl From for HashMap { + + #[cfg(test)] + mod tests { +- use super::HetznerMetadata; ++ use super::{Metadata, PrivateNetwork}; + + #[test] + fn test_metadata_deserialize() { +@@ -141,11 +173,39 @@ public-ipv4: 1.2.3.4 + region: eu-central + public-keys: []"#; + +- let meta: HetznerMetadata = serde_yaml::from_str(body).unwrap(); ++ let meta: Metadata = serde_yaml::from_str(body).unwrap(); + + assert_eq!(meta.availability_zone.unwrap(), "hel1-dc2"); + assert_eq!(meta.hostname.unwrap(), "my-server"); + assert_eq!(meta.instance_id.unwrap(), 42); + assert_eq!(meta.public_ipv4.unwrap(), "1.2.3.4"); + } ++ ++ #[test] ++ fn test_private_networks_deserialize() { ++ let body = r"- ip: 10.0.0.2 ++ alias_ips: [] ++ interface_num: 2 ++ mac_address: 86:00:00:98:40:6e ++ network_id: 4124728 ++ network_name: foo ++ network: 10.0.0.0/16 ++ subnet: 10.0.0.0/24 ++ gateway: 10.0.0.1 ++- ip: 10.128.0.2 ++ alias_ips: [] ++ interface_num: 1 ++ mac_address: 86:00:00:98:40:6d ++ network_id: 4451335 ++ network_name: bar ++ network: 10.128.0.0/16 ++ subnet: 10.128.0.0/16 ++ gateway: 10.128.0.1"; ++ ++ let private_networks: Vec = serde_yaml::from_str(body).unwrap(); ++ ++ assert_eq!(private_networks.len(), 2); ++ assert_eq!(private_networks[0].ip.clone().unwrap(), "10.0.0.2"); ++ assert_eq!(private_networks[1].ip.clone().unwrap(), "10.128.0.2"); ++ } + } +-- +2.44.2 +