Skip to content

Commit 08dd85d

Browse files
cgwaltersallisonkarlitskaya
authored andcommitted
Add get_raw_blob
This is needed for my "registry frontend for containers-storage" project, but should also be useful in general as we've discussed moving checksum verification into callers. Then there's no need for a driver etc. Assisted-by: Gemini Code Assist (for unit tests) Signed-off-by: Colin Walters <[email protected]> Signed-off-by: Allison Karlitskaya <[email protected]>
1 parent e8c8c90 commit 08dd85d

File tree

3 files changed

+379
-37
lines changed

3 files changed

+379
-37
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ futures-util = "0.3.13"
1414
# NOTE when bumping this in a semver-incompatible way, because we re-export it you
1515
# must also bump the semver of this project.
1616
oci-spec = "0.7.0"
17-
rustix = { version = "0.38", features = ["process", "net"] }
17+
rustix = { version = "0.38", features = ["process", "fs", "net"] }
1818
serde = { features = ["derive"], version = "1.0.125" }
1919
serde_json = "1.0.64"
2020
semver = "1.0.4"

examples/client.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,24 @@ struct GetBlobOpts {
2828
size: u64,
2929
}
3030

31+
#[derive(clap::Parser, Debug)]
32+
struct FetchContainerToDevNullOpts {
33+
#[clap(flatten)]
34+
metaopts: GetMetadataOpts,
35+
36+
/// Use the "raw" path for fetching blobs
37+
#[clap(long)]
38+
raw_blobs: bool,
39+
}
40+
3141
/// Simple program to greet a person
3242
#[derive(clap::Parser, Debug)]
3343
#[command(version, about, long_about = None)]
3444
enum Opt {
3545
GetMetadata(GetMetadataOpts),
3646
GetBlob(GetBlobOpts),
37-
FetchContainerToDevNull(GetMetadataOpts),
47+
GetBlobRaw(GetBlobOpts),
48+
FetchContainerToDevNull(FetchContainerToDevNullOpts),
3849
}
3950

4051
#[derive(serde::Serialize, Debug)]
@@ -86,18 +97,49 @@ async fn get_blob(o: GetBlobOpts) -> Result<()> {
8697
Ok(())
8798
}
8899

89-
async fn fetch_container_to_devnull(o: GetMetadataOpts) -> Result<()> {
90-
let config = o.proxy_opts();
100+
async fn get_blob_raw(o: GetBlobOpts) -> Result<()> {
101+
let proxy = containers_image_proxy::ImageProxy::new().await?;
102+
let img = proxy.open_image(&o.reference).await?;
103+
let (_, mut datafd, err) = proxy.get_raw_blob(&img, &o.digest).await?;
104+
105+
let mut stdout = std::io::stdout().lock();
106+
let reader = async move {
107+
let mut buffer = [0u8; 8192];
108+
loop {
109+
let n = datafd.read(&mut buffer).await?;
110+
if n == 0 {
111+
return anyhow::Ok(());
112+
}
113+
stdout.write_all(&buffer[..n])?;
114+
}
115+
};
116+
117+
let (a, b) = tokio::join!(reader, err);
118+
a?;
119+
b?;
120+
Ok(())
121+
}
122+
123+
async fn fetch_container_to_devnull(o: FetchContainerToDevNullOpts) -> Result<()> {
124+
let config = o.metaopts.proxy_opts();
91125
let proxy = containers_image_proxy::ImageProxy::new_with_config(config).await?;
92-
let img = &proxy.open_image(&o.reference).await?;
126+
let img = &proxy.open_image(&o.metaopts.reference).await?;
93127
let manifest = proxy.fetch_manifest(img).await?.1;
94128
for layer in manifest.layers() {
95-
let (mut blob, driver) = proxy.get_descriptor(img, layer).await?;
96129
let mut devnull = tokio::io::sink();
97-
let copier = tokio::io::copy(&mut blob, &mut devnull);
98-
let (copier, driver) = tokio::join!(copier, driver);
99-
copier?;
100-
driver?;
130+
if o.raw_blobs {
131+
let (_, mut blob, err) = proxy.get_raw_blob(img, layer.digest()).await?;
132+
let copier = tokio::io::copy(&mut blob, &mut devnull);
133+
let (copier, err) = tokio::join!(copier, err);
134+
copier?;
135+
err?;
136+
} else {
137+
let (mut blob, driver) = proxy.get_descriptor(img, layer).await?;
138+
let copier = tokio::io::copy(&mut blob, &mut devnull);
139+
let (copier, driver) = tokio::join!(copier, driver);
140+
copier?;
141+
driver?;
142+
}
101143
}
102144
Ok(())
103145
}
@@ -106,6 +148,7 @@ async fn run() -> Result<()> {
106148
match Opt::parse() {
107149
Opt::GetMetadata(o) => get_metadata(o).await,
108150
Opt::GetBlob(o) => get_blob(o).await,
151+
Opt::GetBlobRaw(o) => get_blob_raw(o).await,
109152
Opt::FetchContainerToDevNull(o) => fetch_container_to_devnull(o).await,
110153
}
111154
}

0 commit comments

Comments
 (0)