termoshtt / ocipkg

An OCI registry client for Rust desiged to use distribute static library as a "container"
Apache License 2.0
48 stars 8 forks source link

Bug? - Missing Layer - devcontainers index. #92

Closed CodeMan99 closed 5 months ago

CodeMan99 commented 1 year ago

:wave: hello! Cool project.

I am trying to write a CLI frontend for containers.dev. Mostly for fun and learning of Rust patterns. Also, because the existing cli is pretty hard to use in some cases.

Anyway, the index is what I'm trying download and parse. Using oras cli works fine:

$ oras pull ghcr.io/devcontainers/index:latest
Downloading dc19da93abf6 devcontainer-index.json
Downloaded  dc19da93abf6 devcontainer-index.json
Pulled [registry] ghcr.io/devcontainers/index:latest
Digest: sha256:5b1f261541a481b932cddb8da004a75799f3471368867a2ff0e1a36b9bc8defb
$ ls -l
total 900
-rw-r--r-- 1 vscode vscode 917600 Oct 12 18:12 devcontainer-index.json

This project seems to not like that?

$ ocipkg get ghcr.io/devcontainers/index:latest
[2023-10-12T18:03:12Z INFO  ocipkg::distribution] Get ghcr.io/devcontainers/index:latest into ~/.local/share/ocipkg/ghcr.io/devcontainers/index/__latest
Error: MissingLayer

Or am I mis-using the tool somehow?

CodeMan99 commented 11 months ago

So what I am looking for is something akin to this.

use std::fs::File;
use std::io::Write;
use std::path::Path;

use oci_spec::image::MediaType;
use ocipkg::{Digest, ImageName, distribution};

/// Pull OCI Artifact "ghcr.io/devcontainers/index:latest" and download the JSON layer to the given filename.
pub fn pull_devcontainer_index<P: AsRef<Path>>(filename: P) -> Result<(), Box<dyn std::error::Error>> {
    let image_name = ImageName::parse("ghcr.io/devcontainers/index:latest")?;
    let mut client = distribution::Client::try_from(&image_name)?;
    let layer = distribution::get_image_layer(&mut client, &image_name, |media_type| {
        match media_type {
            MediaType::Other(other_type) => other_type == "application/vnd.devcontainers.index.layer.v1+json",
            _ => false,
        }
    })?;
    let digest = Digest::new(layer.digest())?;
    let blob = client.get_blob(&digest)?;
    let mut file = File::create(filename)?;

    file.write_all(&blob[..])?;

    Ok(())
}

Note that Client::try_from & get_image_layer exist in my fork of this project. I am willing to submit a PR after #93 is merged.

CodeMan99 commented 10 months ago

I've closed #93 in favor of #94. Seems like a less opinionated approach to me.

CodeMan99 commented 6 months ago

Will close this as soon as the next release (to crates.io) occurs!

CodeMan99 commented 5 months ago

Release v0.2.9 includes the contributed work.

Thank you!