coreos-base/afterburn: pull Hetzner patch

* allows Afterburn to get private IPs from Hetzner metadata
service
* fix duplicate attribute prefix

Signed-off-by: Mathieu Tortuyaux <mtortuyaux@microsoft.com>
This commit is contained in:
Mathieu Tortuyaux 2024-07-22 09:37:25 +02:00
parent 417ebf57f6
commit 911386c504
No known key found for this signature in database
GPG Key ID: AC5CCFB52545D9B8
4 changed files with 340 additions and 0 deletions

View File

@ -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() {

View File

@ -0,0 +1,74 @@
From 6effcd345229da6b12d1206681f58e63220c534a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julian=20T=C3=B6lle?= <julian.toelle97@gmail.com>
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 <julian.toelle97@gmail.com>
---
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<HetznerMetadata> for HashMap<String, String> {
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

View File

@ -0,0 +1,262 @@
From 0de46d6282d270004fa19c8981cbbb258afc4ffd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julian=20T=C3=B6lle?= <julian.toelle97@gmail.com>
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 <julian.toelle97@gmail.com>
---
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<std::collections::HashMap<String, String>> {
- let meta: HetznerMetadata = self
+ fn attributes(&self) -> Result<HashMap<String, String>> {
+ let metadata: Metadata = self
.client
.get(retry::Yaml, HETZNER_METADATA_BASE_URL.to_string())
.send()?
.unwrap();
- Ok(meta.into())
+ let private_networks: Vec<PrivateNetwork> = self
+ .client
+ .get(retry::Yaml, Self::endpoint_for("private-networks"))
+ .send()?
+ .unwrap();
+
+ Ok(Attributes {
+ metadata,
+ private_networks,
+ }
+ .into())
}
fn hostname(&self) -> Result<Option<String>> {
@@ -90,9 +100,14 @@ impl MetadataProvider for HetznerProvider {
}
}
+#[derive(Debug, Deserialize)]
+struct PrivateNetwork {
+ ip: Option<String>,
+}
+
#[derive(Debug, Deserialize)]
#[serde(rename_all = "kebab-case")]
-struct HetznerMetadata {
+struct Metadata {
hostname: Option<String>,
instance_id: Option<i64>,
public_ipv4: Option<String>,
@@ -100,8 +115,13 @@ struct HetznerMetadata {
region: Option<String>,
}
-impl From<HetznerMetadata> for HashMap<String, String> {
- fn from(meta: HetznerMetadata) -> Self {
+struct Attributes {
+ metadata: Metadata,
+ private_networks: Vec<PrivateNetwork>,
+}
+
+impl From<Attributes> for HashMap<String, String> {
+ fn from(attributes: Attributes) -> Self {
let mut out = HashMap::with_capacity(5);
let add_value = |map: &mut HashMap<_, _>, key: &str, value: Option<String>| {
@@ -113,16 +133,28 @@ impl From<HetznerMetadata> for HashMap<String, String> {
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<HetznerMetadata> for HashMap<String, String> {
#[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<PrivateNetwork> = 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