Skip to content

Commit 0d91c9c

Browse files
authored
Merge pull request #199 from containers/podman-v5.7
Podman v5.7
2 parents e40f8c9 + 53eb9f5 commit 0d91c9c

14 files changed

Lines changed: 381 additions & 45 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "podlet"
3-
version = "0.3.2-alpha.4"
3+
version = "0.3.2-alpha.5"
44
authors = ["Paul Nettleton <k9@k9withabone.dev>"]
55
edition = "2024"
66
rust-version = "1.85"

src/cli.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod artifact;
12
mod build;
23
mod compose;
34
mod container;
@@ -38,7 +39,7 @@ use crate::quadlet::{
3839
};
3940

4041
use self::{
41-
build::Build, compose::Compose, container::Container, generate::Generate,
42+
artifact::Artifact, build::Build, compose::Compose, container::Container, generate::Generate,
4243
global_args::GlobalArgs, image::Image, install::Install, kube::Kube, network::Network,
4344
pod::Pod, volume::Volume,
4445
};
@@ -623,6 +624,16 @@ enum PodmanCommands {
623624
#[command(subcommand)]
624625
image: Box<Image>,
625626
},
627+
628+
/// Generate a Podman Quadlet `.artifact` file
629+
///
630+
/// For details on options see:
631+
/// https://docs.podman.io/en/stable/markdown/podman-artifact-pull.1.html
632+
Artifact {
633+
/// The \[Artifact\] section
634+
#[command(subcommand)]
635+
artifact: Artifact,
636+
},
626637
}
627638

628639
impl From<PodmanCommands> for quadlet::Resource {
@@ -635,6 +646,7 @@ impl From<PodmanCommands> for quadlet::Resource {
635646
PodmanCommands::Volume { volume } => volume.into(),
636647
PodmanCommands::Build { build } => (*build).into(),
637648
PodmanCommands::Image { image } => (*image).into(),
649+
PodmanCommands::Artifact { artifact } => artifact.into(),
638650
}
639651
}
640652
}
@@ -680,6 +692,7 @@ impl PodmanCommands {
680692
Self::Volume { volume } => volume.name(),
681693
Self::Build { build } => build.name(),
682694
Self::Image { image } => image.name(),
695+
Self::Artifact { artifact } => artifact.name(),
683696
}
684697
}
685698
}

src/cli/artifact.rs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
//! The `podlet podman artifact pull` command and CLI options.
2+
3+
use std::path::PathBuf;
4+
5+
use clap::{Args, Subcommand};
6+
7+
use crate::{
8+
cli::image_to_name,
9+
quadlet::{self, image::DecryptionKey},
10+
};
11+
12+
/// [`Subcommand`]s for `podlet podman artifact`
13+
#[derive(Subcommand, Debug, Clone, PartialEq)]
14+
pub enum Artifact {
15+
/// Generate a Podman Quadlet `.artifact` file
16+
///
17+
/// For details on options see:
18+
/// https://docs.podman.io/en/stable/markdown/podman-pull.1.html and
19+
/// https://docs.podman.io/en/stable/markdown/podman-systemd.unit.5.html#artifact-units-artifact
20+
#[expect(clippy::doc_markdown, reason = "help links")]
21+
#[group(skip)]
22+
Pull {
23+
#[command(flatten)]
24+
pull: Pull,
25+
},
26+
}
27+
28+
impl Artifact {
29+
/// Name suitable for use as the filename of the generated Quadlet file.
30+
pub fn name(&self) -> &str {
31+
let Self::Pull {
32+
pull: Pull { source, .. },
33+
} = self;
34+
35+
image_to_name(source)
36+
}
37+
}
38+
39+
impl From<Artifact> for quadlet::Artifact {
40+
fn from(value: Artifact) -> Self {
41+
let Artifact::Pull { pull } = value;
42+
pull.into()
43+
}
44+
}
45+
46+
impl From<Artifact> for quadlet::Resource {
47+
fn from(value: Artifact) -> Self {
48+
quadlet::Artifact::from(value).into()
49+
}
50+
}
51+
52+
/// [`Args`] for `podman artifact pull`
53+
#[derive(Args, Default, Debug, Clone, PartialEq)]
54+
pub struct Pull {
55+
/// Path of the authentication file.
56+
///
57+
/// Converts to "AuthFile=PATH".
58+
#[arg(long, value_name = "PATH")]
59+
pub authfile: Option<PathBuf>,
60+
61+
/// Use certificates at path (*.crt, *.cert, *.key) to connect to the registry.
62+
///
63+
/// Converts to "CertDir=PATH".
64+
#[arg(long, value_name = "PATH")]
65+
pub cert_dir: Option<PathBuf>,
66+
67+
/// The username and/or password to use to authenticate with the registry, if required.
68+
///
69+
/// Converts to "Creds=[USERNAME][:PASSWORD]".
70+
#[arg(long, value_name = "[USERNAME][:PASSWORD]")]
71+
pub creds: Option<String>,
72+
73+
/// The key and optional passphrase to be used for decryption of artifacts.
74+
///
75+
/// Converts to "DecryptionKey=KEY[:PASSPHRASE]"
76+
#[arg(long, value_name = "KEY[:PASSPHRASE]")]
77+
pub decryption_key: Option<DecryptionKey>,
78+
79+
/// Suppress output information when pulling artifacts.
80+
#[arg(short, long)]
81+
pub quiet: bool,
82+
83+
/// Number of times to retry pulling artifacts.
84+
///
85+
/// Converts to "Retry=ATTEMPTS".
86+
///
87+
/// Default is 3.
88+
#[arg(long, value_name = "ATTEMPTS")]
89+
#[arg(long)]
90+
pub retry: Option<u64>,
91+
92+
/// Duration of delay between retry attempts when pulling artifacts.
93+
///
94+
/// Converts to "RetryDelay=DURATION".
95+
///
96+
/// Default is to start at two seconds and then exponentially back off.
97+
#[arg(long, value_name = "DURATION")]
98+
pub retry_delay: Option<String>,
99+
100+
/// Require HTTPS and verify certificates when contacting registries.
101+
///
102+
/// Converts to "TLSVerify=TLS_VERIFY".
103+
#[expect(clippy::doc_markdown, reason = "Quadlet option")]
104+
#[arg(long, num_args = 0..=1, require_equals = true, default_missing_value = "true")]
105+
pub tls_verify: Option<bool>,
106+
107+
/// The location from which the artifact image is obtained.
108+
pub source: String,
109+
}
110+
111+
impl From<Pull> for quadlet::Artifact {
112+
fn from(
113+
Pull {
114+
authfile,
115+
cert_dir,
116+
creds,
117+
decryption_key,
118+
quiet,
119+
retry,
120+
retry_delay,
121+
tls_verify,
122+
source,
123+
}: Pull,
124+
) -> Self {
125+
Self {
126+
artifact: source,
127+
auth_file: authfile,
128+
cert_dir,
129+
creds,
130+
decryption_key,
131+
podman_args: None,
132+
quiet,
133+
retry,
134+
retry_delay,
135+
tls_verify,
136+
}
137+
}
138+
}

src/cli/build.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ pub struct Build {
5555
#[arg(long, value_name = "PATH")]
5656
authfile: Option<PathBuf>,
5757

58+
/// Specifies a build argument and its value.
59+
///
60+
/// Converts to "BuildArg=ARG=VALUE".
61+
///
62+
/// Can be specified multiple times.
63+
#[expect(clippy::struct_field_names, reason = "CLI arg")]
64+
#[arg(long, value_name = "ARG=VALUE")]
65+
build_arg: Vec<String>,
66+
5867
/// Set custom DNS servers.
5968
///
6069
/// Converts to "DNS=IP_ADDRESS".
@@ -116,6 +125,12 @@ pub struct Build {
116125
#[arg(long, value_name = "GROUP | keep-groups")]
117126
group_add: Vec<String>,
118127

128+
/// Path to an alternative `.containerignore` file.
129+
///
130+
/// Converts to "IgnoreFile=PATH".
131+
#[arg(long, value_name = "PATH")]
132+
ignorefile: Option<PathBuf>,
133+
119134
/// The name assigned to the resulting image if the build process completes successfully.
120135
///
121136
/// Converts to "ImageTag=IMAGE_NAME".
@@ -226,13 +241,15 @@ impl From<Build> for quadlet::Build {
226241
annotation,
227242
arch,
228243
authfile,
244+
build_arg,
229245
dns,
230246
dns_option,
231247
dns_search,
232248
env,
233249
file,
234250
force_rm,
235251
group_add,
252+
ignorefile,
236253
tag,
237254
label,
238255
network,
@@ -254,13 +271,15 @@ impl From<Build> for quadlet::Build {
254271
annotation,
255272
arch,
256273
auth_file: authfile,
274+
build_arg,
257275
dns: dns.into(),
258276
dns_option,
259277
dns_search,
260278
environment: env,
261279
file,
262280
force_rm,
263281
group_add,
282+
ignore_file: ignorefile,
264283
image_tag: tag,
265284
label,
266285
network,
@@ -338,7 +357,6 @@ impl TryFrom<service::Build> for Build {
338357
.into_iter()
339358
.map(|(hostname, ip)| format!("{hostname}:{ip}"))
340359
.collect(),
341-
build_arg: args.into_list().into_iter().collect(),
342360
build_context: additional_contexts
343361
.iter()
344362
.map(|(id, context)| format!("{id}={context}"))
@@ -386,6 +404,7 @@ impl TryFrom<service::Build> for Build {
386404

387405
Ok(Self {
388406
file,
407+
build_arg: args.into_list().into_iter().collect(),
389408
tag: tags.into_iter().map(Into::into).collect(),
390409
label: labels.into_list().into_iter().collect(),
391410
network: network.map(Into::into).into_iter().collect(),
@@ -434,12 +453,6 @@ struct PodmanArgs {
434453
#[serde(skip_serializing_if = "Not::not")]
435454
all_platforms: bool,
436455

437-
/// Specifies a build argument and its value.
438-
///
439-
/// Can be specified multiple times.
440-
#[arg(long, value_name = "ARG=VALUE")]
441-
build_arg: Vec<String>,
442-
443456
/// Specifies a file containing lines of build arguments of the form `arg=value`.
444457
///
445458
/// Can be specified multiple times.
@@ -587,10 +600,6 @@ struct PodmanArgs {
587600
#[default = true]
588601
identity_label: bool,
589602

590-
/// Path to an alternative `.containerignore` file.
591-
#[arg(long, value_name = "PATH")]
592-
ignorefile: Option<PathBuf>,
593-
594603
/// Write the built image's ID to a file.
595604
#[arg(long, value_name = "IMAGE_ID_FILE")]
596605
iidfile: Option<PathBuf>,

src/cli/container/podman.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ pub struct PodmanArgs {
5252
#[arg(long, value_name = "DEVICE:WEIGHT")]
5353
blkio_weight_device: Vec<String>,
5454

55+
/// Use certificates in the specified directory to connect to the registry
56+
#[arg(long, value_name = "PATH")]
57+
cert_dir: Option<PathBuf>,
58+
5559
/// Specify the cgroup file to write to and its value
5660
///
5761
/// Can be specified multiple times
@@ -110,6 +114,10 @@ pub struct PodmanArgs {
110114
#[arg(long, value_name = "NODES")]
111115
cpuset_mems: Option<String>,
112116

117+
/// The username and/or password to use to authenticate with the registry, if required
118+
#[arg(long, value_name = "[USERNAME][:PASSWORD]")]
119+
creds: Option<String>,
120+
113121
/// Key needed to decrypt the image
114122
#[arg(long, value_name = "KEY[:PASSPHRASE]")]
115123
decryption_key: Option<String>,
@@ -184,12 +192,6 @@ pub struct PodmanArgs {
184192
#[arg(long, value_name = "NAME")]
185193
hostuser: Vec<String>,
186194

187-
/// Set proxy environment variables in the container based on the host proxy vars
188-
#[arg(long, action = ArgAction::Set, default_value_t = true)]
189-
#[serde(skip_serializing_if = "skip_true")]
190-
#[default = true]
191-
http_proxy: bool,
192-
193195
/// How to handle the builtin image volumes
194196
#[arg(long, value_name = "bind | tmpfs | ignore")]
195197
image_volume: Option<String>,

src/cli/container/quadlet.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,13 @@ pub struct QuadletOptions {
262262
#[arg(short, long, value_name = "NAME")]
263263
hostname: Option<String>,
264264

265+
/// Set proxy environment variables in the container based on the host proxy vars
266+
///
267+
/// Converts to "HttpProxy=true|false"
268+
#[arg(long, action = ArgAction::Set, default_value_t = true)]
269+
#[default = true]
270+
http_proxy: bool,
271+
265272
/// Specify a static IPv4 address for the container
266273
///
267274
/// Converts to "IP=IPV4"
@@ -564,6 +571,7 @@ impl From<QuadletOptions> for crate::quadlet::Container {
564571
health_startup_timeout,
565572
health_timeout,
566573
hostname: host_name,
574+
http_proxy,
567575
ip,
568576
ip6,
569577
mut label,
@@ -646,6 +654,7 @@ impl From<QuadletOptions> for crate::quadlet::Container {
646654
health_startup_timeout,
647655
health_timeout,
648656
host_name,
657+
http_proxy,
649658
ip,
650659
ip6,
651660
label,

0 commit comments

Comments
 (0)