mirror of
https://github.com/podman-desktop/podman-desktop
synced 2026-05-24 10:18:53 +00:00
chore: add isManifest function to determine a manifest
### What does this PR do? Adds a guessIsManifest function to try and determine if an image is a manifest or not: - By checking the repotags and digests - Checking labels does not exist, as labels are not added when creating a manifest - VirtualSize is under 1MB as a manifest list is just text that points to other images We are unable to check the history (manifest commonly has no history) as Dockerode API does not support getting the history of the image. ### Screenshot / video of UI <!-- If this PR is changing UI, please include screenshots or screencasts showing the difference --> N/A ### What issues does this PR fix or reference? <!-- Include any related issues from Podman Desktop repository (or from another issue tracker). --> Closes containers#6690 ### How to test this PR? <!-- Please explain steps to verify the functionality, do not forget to provide unit/component tests --> - [X] Tests are covering the bug fix or the new feature Signed-off-by: Charlie Drage <charlie@charliedrage.com>
This commit is contained in:
parent
b003d15ce7
commit
006e65bfb6
3 changed files with 76 additions and 0 deletions
|
|
@ -25,6 +25,7 @@ export interface ImageInfo extends Dockerode.ImageInfo {
|
|||
engineId: string;
|
||||
engineName: string;
|
||||
History?: string[];
|
||||
isManifest?: boolean;
|
||||
}
|
||||
|
||||
export interface BuildImageOptions {
|
||||
|
|
|
|||
|
|
@ -4391,3 +4391,73 @@ describe('loadImages', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('manifest is listed as true with podmanListImages correctly', async () => {
|
||||
const manifestImage: ImageInfo = {
|
||||
Id: 'manifestImage',
|
||||
Labels: {},
|
||||
engineId: 'engine1',
|
||||
engineName: 'podman',
|
||||
ParentId: '',
|
||||
RepoTags: ['manifestTag'],
|
||||
RepoDigests: ['manifestDigest'],
|
||||
Created: 0,
|
||||
Size: 0,
|
||||
VirtualSize: 40 * 1024, // 40KB (less than 50KB threshold)
|
||||
SharedSize: 0,
|
||||
Containers: 0,
|
||||
};
|
||||
|
||||
const regularImage: ImageInfo = {
|
||||
Id: 'ee301c921b8aadc002973b2e0c3da17d701dcd994b606769a7e6eaa100b81d44',
|
||||
Labels: {},
|
||||
engineId: 'engine5', // Assuming 'engineId' and 'engineName' are part of your ImageInfo but not relevant here
|
||||
engineName: 'podman',
|
||||
ParentId: '',
|
||||
RepoTags: ['testdomain.io/library/hello:latest'],
|
||||
RepoDigests: [
|
||||
'testdomain.io/library/hello@sha256:2d4e459f4ecb5329407ae3e47cbc107a2fbace221354ca75960af4c047b3cb13',
|
||||
'testdomain.io/library/hello@sha256:53641cd209a4fecfc68e21a99871ce8c6920b2e7502df0a20671c6fccc73a7c6',
|
||||
],
|
||||
Created: 1683046167,
|
||||
Size: 23301,
|
||||
VirtualSize: 23301, // Directly matches Size in this case
|
||||
SharedSize: 0,
|
||||
Containers: 0,
|
||||
History: ['testdomain.io/library/hello:latest'],
|
||||
};
|
||||
|
||||
const imagesList = [manifestImage, regularImage];
|
||||
nock('http://localhost').get('/v4.2.0/libpod/images/json').reply(200, imagesList);
|
||||
const api = new Dockerode({ protocol: 'http', host: 'localhost' });
|
||||
|
||||
// set provider
|
||||
containerRegistry.addInternalProvider('podman', {
|
||||
name: 'podman',
|
||||
id: 'podman1',
|
||||
api,
|
||||
libpodApi: api,
|
||||
connection: {
|
||||
type: 'podman',
|
||||
},
|
||||
} as unknown as InternalContainerProvider);
|
||||
|
||||
const images = await containerRegistry.podmanListImages();
|
||||
// ensure the field are correct
|
||||
expect(images).toBeDefined();
|
||||
expect(images).toHaveLength(2);
|
||||
|
||||
// Check the first image
|
||||
const image = images[0];
|
||||
expect(image.engineId).toBe('podman1');
|
||||
expect(image.engineName).toBe('podman');
|
||||
expect(image.Id).toBe('manifestImage');
|
||||
expect(image.isManifest).toBe(true);
|
||||
|
||||
// Check the second image
|
||||
const image2 = images[1];
|
||||
expect(image2.engineId).toBe('podman1');
|
||||
expect(image2.engineName).toBe('podman');
|
||||
expect(image2.Id).toBe('ee301c921b8aadc002973b2e0c3da17d701dcd994b606769a7e6eaa100b81d44');
|
||||
expect(image2.isManifest).toBe(false);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ import { Emitter } from './events/emitter.js';
|
|||
import type { ImageRegistry } from './image-registry.js';
|
||||
import type { Telemetry } from './telemetry/telemetry.js';
|
||||
import { Disposable } from './types/disposable.js';
|
||||
import { guessIsManifest } from './util/manifest.js';
|
||||
|
||||
const tar: { pack: (dir: string) => NodeJS.ReadableStream } = require('tar-fs');
|
||||
|
||||
|
|
@ -626,6 +627,10 @@ export class ContainerProviderRegistry {
|
|||
...image,
|
||||
engineName: provider.name,
|
||||
engineId: provider.id,
|
||||
// Using guessIsManifest, determine if the image is a manifest and set isManifest accordingly
|
||||
// NOTE: This is a workaround until we have a better way to determine if an image is a manifest
|
||||
// and may result in false positives until issue: https://github.com/containers/podman/issues/22184 is resolved
|
||||
isManifest: guessIsManifest(image),
|
||||
}));
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue