Skip to content

Commit

Permalink
Add support for OCI Image Manifest
Browse files Browse the repository at this point in the history
Image like s390x/ubuntu uses OCI Image Manifest, which per
https://github.com/opencontainers/image-spec/blob/v1.0.1/manifest.md
is very similar to vnd.docker.distribution.manifest.v2.

Add a test to confirm we can deserialize an OCI Image Manifest as a ManifestSchema2Spec.

Also add a test to confirm that we can now fetch the manifest from docker.io.
Previously it would fail with MANIFEST_UNKNOWN.
  • Loading branch information
chantra committed Feb 9, 2024
1 parent c8bad71 commit 0a337d4
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 2 deletions.
5 changes: 5 additions & 0 deletions src/mediatypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ pub enum MediaTypes {
#[strum(serialize = "application/vnd.docker.container.image.v1+json")]
#[strum(props(Sub = "vnd.docker.container.image.v1+json"))]
ContainerConfigV1,
/// OCI Manifest
#[strum(serialize = "application/vnd.oci.image.manifest.v1+json")]
#[strum(props(Sub = "vnd.oci.image.manifest.v1+json"))]
OciImageManifest,
/// Generic JSON
#[strum(serialize = "application/json")]
#[strum(props(Sub = "json"))]
Expand All @@ -55,6 +59,7 @@ impl MediaTypes {
}
("vnd.docker.image.rootfs.diff.tar.gzip", _) => Ok(MediaTypes::ImageLayerTgz),
("vnd.docker.container.image.v1", "json") => Ok(MediaTypes::ContainerConfigV1),
("vnd.oci.image.manifest.v1", "json") => Ok(MediaTypes::OciImageManifest),
_ => Err(crate::Error::UnknownMimeType(mtype.clone())),
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/v2/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ impl Config {
(MediaTypes::ManifestV2S2, Some(0.5)),
(MediaTypes::ManifestV2S1Signed, Some(0.4)),
(MediaTypes::ManifestList, Some(0.5)),
(MediaTypes::OciImageManifest, Some(0.5)),
],
// GCR incorrectly parses `q` parameters, so we use special Accept for it.
// Bug: https://issuetracker.google.com/issues/159827510.
Expand All @@ -122,6 +123,7 @@ impl Config {
(MediaTypes::ManifestV2S2, None),
(MediaTypes::ManifestV2S1Signed, None),
(MediaTypes::ManifestList, None),
(MediaTypes::OciImageManifest, None),
],
},
};
Expand Down
2 changes: 1 addition & 1 deletion src/v2/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl Client {
.map(Manifest::S1Signed)?,
content_digest,
)),
mediatypes::MediaTypes::ManifestV2S2 => {
mediatypes::MediaTypes::ManifestV2S2 | mediatypes::MediaTypes::OciImageManifest => {
let m = res.json::<ManifestSchema2Spec>().await?;
Ok((
m.fetch_config_blob(client_spare0, name.to_string())
Expand Down
16 changes: 16 additions & 0 deletions tests/fixtures/manifest_oci_image_manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 2297,
"digest": "sha256:7324f32f94760ec1dc237858203ea520fc4e6dfbd0bc018f392e54b1392ac722"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 28028344,
"digest": "sha256:b2afc8f0dccbc5496c814ae03ac3fff7e86393abd18b2d2910a9c489bfe64311"
}
]
}
7 changes: 7 additions & 0 deletions tests/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ fn test_manifest_v2s2() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}

#[test]
fn test_deserialize_oci_image_manifest() {
let f = fs::File::open("tests/fixtures/manifest_oci_image_manifest.json").expect("Missing fixture");
let bufrd = io::BufReader::new(f);
let _manif: dkregistry::v2::manifest::ManifestSchema2Spec = serde_json::from_reader(bufrd).unwrap();
}

#[test]
fn test_deserialize_manifest_list_v2() {
let f = fs::File::open("tests/fixtures/manifest_list_v2.json").expect("Missing fixture");
Expand Down
27 changes: 26 additions & 1 deletion tests/net/docker_io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,29 @@ fn test_dockerio_anonymous_non_existent_image() {
let res = runtime.block_on(futcheck);
assert_eq!(res.is_ok(), false);
assert!(matches!(res, Err(errors::Error::Api(_))));
}
}

/// Test that we can deserialize OCI image manifest, as is
/// returned for s390x/ubuntu image.
#[test]
fn test_dockerio_anonymous_auth_oci_manifest() {
let runtime = Runtime::new().unwrap();
let image = "s390x/ubuntu";
let version = "latest";
let login_scope = format!("repository:{}:pull", image);
let scopes = vec![login_scope.as_str()];
let dclient_future = dkregistry::v2::Client::configure()
.registry(REGISTRY)
.insecure_registry(false)
.username(None)
.password(None)
.build()
.unwrap()
.authenticate(scopes.as_slice());

let dclient = runtime.block_on(dclient_future).unwrap();
let futcheck = dclient.get_manifest(image, version);

let res = runtime.block_on(futcheck);
assert_eq!(res.is_ok(), true);
}

0 comments on commit 0a337d4

Please sign in to comment.