Skip to content

Commit

Permalink
Merge pull request #21 from cgwalters/proxy-config
Browse files Browse the repository at this point in the history
imageproxy: Add a method to get image configuration
  • Loading branch information
cgwalters committed Dec 8, 2021
2 parents 06f7281 + 341a3b3 commit 5ea91ae
Showing 1 changed file with 46 additions and 9 deletions.
55 changes: 46 additions & 9 deletions src/imageproxy.rs
Expand Up @@ -32,6 +32,10 @@ lazy_static::lazy_static! {
static ref SUPPORTED_PROTO_VERSION: semver::VersionReq = {
semver::VersionReq::parse("0.2.0").unwrap()
};
// https://github.com/containers/skopeo/pull/1523
static ref SEMVER_0_2_3: semver::VersionReq = {
semver::VersionReq::parse("0.2.3").unwrap()
};
}

#[derive(Serialize)]
Expand Down Expand Up @@ -77,6 +81,7 @@ type ChildFuture = Pin<
pub struct ImageProxy {
sockfd: Arc<Mutex<File>>,
childwait: Arc<AsyncMutex<ChildFuture>>,
protover: semver::Version,
}

impl std::fmt::Debug for ImageProxy {
Expand Down Expand Up @@ -204,9 +209,10 @@ impl ImageProxy {
let childwait = tokio::task::spawn_blocking(move || child.wait_with_output());
let sockfd = Arc::new(Mutex::new(mysock));

let r = Self {
let mut r = Self {
sockfd,
childwait: Arc::new(AsyncMutex::new(Box::pin(childwait))),
protover: semver::Version::new(0, 0, 0),
};

// Verify semantic version
Expand All @@ -220,10 +226,20 @@ impl ImageProxy {
supported
));
}
r.protover = protover;

Ok(r)
}

/// If the proxy supports at least semver 0.2.3, return a wrapper with methods from that version.
pub fn get_0_2_3(&self) -> Option<ImageProxy0_2_3<'_>> {
if SEMVER_0_2_3.matches(&self.protover) {
Some(ImageProxy0_2_3 { proxy: self })
} else {
None
}
}

async fn impl_request_raw<T: serde::de::DeserializeOwned + Send + 'static>(
sockfd: Arc<Mutex<File>>,
req: Request,
Expand Down Expand Up @@ -328,18 +344,22 @@ impl ImageProxy {
Ok(r)
}

async fn read_all_fd(&self, fd: Option<(File, u32)>) -> Result<Vec<u8>> {
let (fd, pipeid) = fd.ok_or_else(|| anyhow!("Missing fd from reply"))?;
let mut fd = tokio::io::BufReader::new(tokio::fs::File::from_std(fd));
let mut r = Vec::new();
let reader = fd.read_to_end(&mut r);
let (nbytes, finish) = tokio::join!(reader, self.finish_pipe(pipeid));
finish?;
assert_eq!(nbytes?, r.len());
Ok(r)
}

/// Fetch the manifest.
/// For more information on OCI manifests, see <https://github.com/opencontainers/image-spec/blob/main/manifest.md>
pub async fn fetch_manifest(&self, img: &OpenedImage) -> Result<(String, Vec<u8>)> {
let (digest, fd) = self.impl_request("GetManifest", [img.0]).await?;
let (fd, pipeid) = fd.ok_or_else(|| anyhow!("Missing fd from reply"))?;
let mut fd = tokio::io::BufReader::new(tokio::fs::File::from_std(fd));
let mut manifest = Vec::new();
let reader = fd.read_to_end(&mut manifest);
let (reader, finish) = tokio::join!(reader, self.finish_pipe(pipeid));
reader?;
finish?;
Ok((digest, manifest))
Ok((digest, self.read_all_fd(fd).await?))
}

/// Fetch a blob identified by e.g. `sha256:<digest>`.
Expand Down Expand Up @@ -389,6 +409,23 @@ impl ImageProxy {
}
}

/// A proxy which implements methods from 0.2.3 or newer.
pub struct ImageProxy0_2_3<'a> {
proxy: &'a ImageProxy,
}

impl<'a> ImageProxy0_2_3<'a> {
/// Fetch the config.
/// For more information on OCI config, see <https://github.com/opencontainers/image-spec/blob/main/config.md>
pub async fn fetch_config(&self, img: &OpenedImage) -> Result<Vec<u8>> {
let (_, fd) = self
.proxy
.impl_request::<(), _, _>("GetFullConfig", [img.0])
.await?;
self.proxy.read_all_fd(fd).await
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 5ea91ae

Please sign in to comment.