From c2a79ca5808eaeec8fcdbd3f47bc9acb15208019 Mon Sep 17 00:00:00 2001 From: Cristian Filipescu Date: Tue, 28 Jul 2026 11:04:09 -0700 Subject: [PATCH 1/3] fix(compose): support explicit network names Signed-off-by: Cristian Filipescu --- src/cli/network.rs | 1 + src/quadlet/network.rs | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cli/network.rs b/src/cli/network.rs index 8337363..4d8290a 100644 --- a/src/cli/network.rs +++ b/src/cli/network.rs @@ -175,6 +175,7 @@ impl From for crate::quadlet::Network { ip_range, ipv6, label, + name: None, options: opt, podman_args: (!podman_args.is_empty()).then_some(podman_args), subnet, diff --git a/src/quadlet/network.rs b/src/quadlet/network.rs index a44e26b..87bc3dd 100644 --- a/src/quadlet/network.rs +++ b/src/quadlet/network.rs @@ -54,6 +54,10 @@ pub struct Network { #[serde(serialize_with = "seq_quote_whitespace")] pub label: Vec, + /// Override the name of the Podman network created by this Quadlet. + #[serde(rename = "NetworkName")] + pub name: Option, + /// Set driver specific options. pub options: Vec, @@ -126,7 +130,6 @@ impl TryFrom for Network { let unsupported_options = [ ("attachable", !attachable), - ("name", name.is_none()), ("ipam.options", ipam_options.is_empty()), ]; for (option, not_present) in unsupported_options { @@ -147,6 +150,7 @@ impl TryFrom for Network { ipam_driver, internal, label: labels.into_list().into_iter().collect(), + name, ..Self::default() }; @@ -270,4 +274,19 @@ mod tests { ); Ok(()) } + + #[test] + fn compose_network_name() -> Result<(), crate::serde::quadlet::Error> { + let network = compose_spec::Network { + name: Some("explicit-network-name".into()), + ..compose_spec::Network::default() + }; + let network = Network::try_from(network).unwrap(); + + assert_eq!( + crate::serde::quadlet::to_string_join_all(network)?, + "[Network]\nNetworkName=explicit-network-name\n" + ); + Ok(()) + } } From 4ad4eaf3e27b5954e6bfd30e8086dbf363e407cd Mon Sep 17 00:00:00 2001 From: Cristian Filipescu Date: Sat, 5 Sep 2026 12:45:31 -0700 Subject: [PATCH 2/3] fix(quadlet): validate network name compatibility Signed-off-by: Cristian Filipescu --- src/quadlet/network.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/quadlet/network.rs b/src/quadlet/network.rs index 87bc3dd..eecaa3a 100644 --- a/src/quadlet/network.rs +++ b/src/quadlet/network.rs @@ -86,6 +86,14 @@ impl Downgrade for Network { } if version < PodmanVersion::V4_7 { + if let Some(name) = self.name.take() { + return Err(DowngradeError::Option { + quadlet_option: "NetworkName", + value: name, + supported_version: PodmanVersion::V4_7, + }); + } + for dns in std::mem::take(&mut self.dns) { self.push_arg("dns", &dns); } @@ -289,4 +297,31 @@ mod tests { ); Ok(()) } + + #[test] + fn network_name_added_in_v4_7() -> color_eyre::Result<()> { + let mut network = Network { + name: Some("explicit-network-name".into()), + ..Network::default() + }; + + let error = network + .downgrade(PodmanVersion::V4_6) + .err() + .ok_or_else(|| eyre!("expected NetworkName to be rejected before Podman v4.7"))?; + + assert_eq!( + error.to_string(), + "Quadlet option `NetworkName=explicit-network-name` was not supported until Podman v4.7" + ); + + let mut network = Network { + name: Some("explicit-network-name".into()), + ..Network::default() + }; + + network.downgrade(PodmanVersion::V4_7)?; + assert_eq!(network.name.as_deref(), Some("explicit-network-name")); + Ok(()) + } } From 568b64189f221d91b55aa37619d169dda5912890 Mon Sep 17 00:00:00 2001 From: Cristian Filipescu Date: Sat, 5 Sep 2026 12:45:31 -0700 Subject: [PATCH 3/3] refactor(quadlet): rename network name field Signed-off-by: Cristian Filipescu --- src/cli/network.rs | 2 +- src/quadlet/network.rs | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/cli/network.rs b/src/cli/network.rs index 4d8290a..b241604 100644 --- a/src/cli/network.rs +++ b/src/cli/network.rs @@ -175,7 +175,7 @@ impl From for crate::quadlet::Network { ip_range, ipv6, label, - name: None, + network_name: None, options: opt, podman_args: (!podman_args.is_empty()).then_some(podman_args), subnet, diff --git a/src/quadlet/network.rs b/src/quadlet/network.rs index eecaa3a..10efcec 100644 --- a/src/quadlet/network.rs +++ b/src/quadlet/network.rs @@ -55,8 +55,8 @@ pub struct Network { pub label: Vec, /// Override the name of the Podman network created by this Quadlet. - #[serde(rename = "NetworkName")] - pub name: Option, + #[expect(clippy::struct_field_names, reason = "Quadlet option")] + pub network_name: Option, /// Set driver specific options. pub options: Vec, @@ -86,10 +86,10 @@ impl Downgrade for Network { } if version < PodmanVersion::V4_7 { - if let Some(name) = self.name.take() { + if let Some(network_name) = self.network_name.take() { return Err(DowngradeError::Option { quadlet_option: "NetworkName", - value: name, + value: network_name, supported_version: PodmanVersion::V4_7, }); } @@ -125,7 +125,7 @@ impl TryFrom for Network { ipam, internal, labels, - name, + name: network_name, extensions, }: compose_spec::Network, ) -> Result { @@ -158,7 +158,7 @@ impl TryFrom for Network { ipam_driver, internal, label: labels.into_list().into_iter().collect(), - name, + network_name, ..Self::default() }; @@ -301,7 +301,7 @@ mod tests { #[test] fn network_name_added_in_v4_7() -> color_eyre::Result<()> { let mut network = Network { - name: Some("explicit-network-name".into()), + network_name: Some("explicit-network-name".into()), ..Network::default() }; @@ -316,12 +316,15 @@ mod tests { ); let mut network = Network { - name: Some("explicit-network-name".into()), + network_name: Some("explicit-network-name".into()), ..Network::default() }; network.downgrade(PodmanVersion::V4_7)?; - assert_eq!(network.name.as_deref(), Some("explicit-network-name")); + assert_eq!( + network.network_name.as_deref(), + Some("explicit-network-name") + ); Ok(()) } }