Skip to content

Commit 1ffeeca

Browse files
authored
Merge pull request #83 from cgwalters/get-raw-blob
Add GetBlobRaw
2 parents c92e522 + 6f6622b commit 1ffeeca

File tree

3 files changed

+382
-72
lines changed

3 files changed

+382
-72
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ tokio = { features = ["fs", "io-util", "macros", "process", "rt", "sync"], versi
2323
tracing = "0.1"
2424
# We support versions 2, 3 and 4
2525
cap-std-ext = ">= 2.0, <= 4.0"
26+
itertools = "0.14.0"
2627

2728
[dev-dependencies]
2829
anyhow = "1.0"

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)