chore: handle docker manifests in addition to the OCI manifests

some registries/tooling might use old metadata

related to https://github.com/containers/podman-desktop/issues/6226
Signed-off-by: Florent Benoit <fbenoit@redhat.com>
This commit is contained in:
Florent Benoit 2024-03-04 13:28:47 +04:00 committed by Florent BENOIT
parent 76a2d09d76
commit 3b0d8a208f
2 changed files with 55 additions and 3 deletions

View file

@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (C) 2022 Red Hat, Inc.
* Copyright (C) 2022-2024 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -661,6 +661,53 @@ test('getManifestFromUrl returns the expected manifest without mediaType but wit
expect(spyGetBestManifest).toHaveBeenCalled();
});
test('getManifestFromUrl returns the expected manifest with docker manifest v2', async () => {
const fakeManifest = {
schemaVersion: 2,
mediaType: 'application/vnd.docker.distribution.manifest.list.v2+json',
manifests: [
{
name: 'docker-manifest',
mediaType: 'application/vnd.docker.distribution.manifest.v2+json',
},
{
name: 'unknown-manifest',
mediaType: 'unknown',
},
],
};
// image index
nock('https://my-podman-desktop-fake-registry.io').get('/v2/foo/bar/manifests/latest').reply(200, fakeManifest);
// digest
nock('https://my-podman-desktop-fake-registry.io')
.get('/v2/foo/bar/manifests/1234')
.reply(200, JSON.stringify({ endManifest: true }));
// mock getBestManifest
const spyGetBestManifest = vi.spyOn(imageRegistry, 'getBestManifest');
spyGetBestManifest.mockReturnValue({
digest: 1234,
});
const manifest = await imageRegistry.getManifest(
{
name: 'foo/bar',
tag: 'latest',
registry: 'my-podman-desktop-fake-registry.io',
registryURL: 'https://my-podman-desktop-fake-registry.io/v2',
},
'dummyToken',
);
expect(manifest).toBeDefined();
expect(manifest).toHaveProperty('endManifest', true);
expect(spyGetBestManifest).toHaveBeenCalled();
// check first item of the call and first element of the array
expect(spyGetBestManifest.mock.calls[0][0][0]).contains({ name: 'docker-manifest' });
});
test('getAuthconfigForServer returns the expected authconfig', async () => {
imageRegistry.registerRegistry({
serverUrl: 'my-podman-desktop-fake-registry.io',

View file

@ -622,6 +622,7 @@ export class ImageRegistry {
if (
parsedManifest.schemaVersion === 2 &&
(parsedManifest.mediaType === 'application/vnd.oci.image.index.v1+json' ||
parsedManifest.mediaType === 'application/vnd.docker.distribution.manifest.list.v2+json' ||
Array.isArray(parsedManifest.manifests))
) {
// need to grab correct manifest from the index corresponding to our platform
@ -642,8 +643,12 @@ export class ImageRegistry {
}
// find the manifest corresponding to our platform
const matchedManifest = this.getBestManifest(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
parsedManifest.manifests.filter((m: any) => m.mediaType === 'application/vnd.oci.image.manifest.v1+json'),
parsedManifest.manifests.filter(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(m: any) =>
m.mediaType === 'application/vnd.oci.image.manifest.v1+json' ||
m.mediaType === 'application/vnd.docker.distribution.manifest.v2+json',
),
platformArch,
platformOs,
);