diff --git a/packages/main/src/plugin/container-registry.spec.ts b/packages/main/src/plugin/container-registry.spec.ts index 4dae3d9c2..d379eda14 100644 --- a/packages/main/src/plugin/container-registry.spec.ts +++ b/packages/main/src/plugin/container-registry.spec.ts @@ -5856,3 +5856,88 @@ test('resolve Dokcer image shortname to FQN', async () => { expect(imagesNames.length).toBe(1); expect(imagesNames[0]).toBe('shortname'); }); + +describe('prune images', () => { + const dockerProvider: InternalContainerProvider = { + name: 'docker', + id: 'docker1', + api: { + pruneImages: vi.fn(), + } as unknown as Dockerode, + libpodApi: undefined, + connection: { + type: 'docker', + name: 'docker', + displayName: 'docker', + endpoint: { + socketPath: '/endpoint1.sock', + }, + status: vi.fn(), + }, + }; + + const podmanProvider: InternalContainerProvider = { + name: 'podman', + id: 'podman1', + api: undefined, + libpodApi: { + pruneAllImages: vi.fn(), + } as unknown as LibPod, + connection: { + type: 'podman', + name: 'podman', + displayName: 'podman', + endpoint: { + socketPath: '/endpoint1.sock', + }, + status: vi.fn(), + }, + }; + beforeEach(() => { + vi.resetAllMocks(); + }); + + test('prune all with podman ', async () => { + // set provider + containerRegistry.addInternalProvider('podman.podman', podmanProvider); + + // call + await containerRegistry.pruneImages('podman.podman', true); + + // check we called the libpodApi + expect(podmanProvider.libpodApi?.pruneAllImages).toBeCalledWith(true); + }); + + test('prune partial with podman ', async () => { + // set provider + containerRegistry.addInternalProvider('podman.podman', podmanProvider); + + // call + await containerRegistry.pruneImages('podman.podman', false); + + // check we called the libpodApi + expect(podmanProvider.libpodApi?.pruneAllImages).toBeCalledWith(false); + }); + + test('prune all with docker ', async () => { + // set provider + containerRegistry.addInternalProvider('docker.docker', dockerProvider); + + // call + await containerRegistry.pruneImages('docker.docker', true); + + // check we called the api + expect(dockerProvider.api?.pruneImages).toBeCalledWith({ filters: { dangling: { false: true } } }); + }); + + test('prune partial with docker ', async () => { + // set provider + containerRegistry.addInternalProvider('docker.docker', dockerProvider); + + // call + await containerRegistry.pruneImages('docker.docker', false); + + // check we called the api + expect(dockerProvider.api?.pruneImages).toBeCalledWith({ filters: { dangling: { false: false } } }); + }); +}); diff --git a/packages/main/src/plugin/container-registry.ts b/packages/main/src/plugin/container-registry.ts index 812df5780..a69cf3a25 100644 --- a/packages/main/src/plugin/container-registry.ts +++ b/packages/main/src/plugin/container-registry.ts @@ -671,7 +671,7 @@ export class ContainerProviderRegistry { return images.flat(); } - async pruneImages(engineId: string): Promise { + async pruneImages(engineId: string, all: boolean): Promise { // We have to use two different API calls for pruning images, because the Podman API does not respect the 'dangling' filter // and instead uses 'all' and 'external'. See: https://github.com/containers/podman/issues/11576 // so for Dockerode we'll have to call pruneImages with the 'dangling' filter, and for Podman we'll have to call pruneImages @@ -683,13 +683,13 @@ export class ContainerProviderRegistry { try { const provider = this.internalProviders.get(engineId); if (provider?.libpodApi) { - await provider.libpodApi.pruneAllImages(true); + await provider.libpodApi.pruneAllImages(all); return; } // DOCKER: // Return Promise for this call, because Dockerode does not return anything - await this.getMatchingEngine(engineId).pruneImages({ filters: { dangling: { false: true } } }); + await this.getMatchingEngine(engineId).pruneImages({ filters: { dangling: { false: all } } }); } catch (error) { telemetryOptions = { error: error }; throw error; diff --git a/packages/main/src/plugin/index.ts b/packages/main/src/plugin/index.ts index 9568d2d10..cab0f747d 100644 --- a/packages/main/src/plugin/index.ts +++ b/packages/main/src/plugin/index.ts @@ -1007,9 +1007,12 @@ export class PluginSystem { return containerProviderRegistry.prunePods(engine); }); - this.ipcHandle('container-provider-registry:pruneImages', async (_listener, engine: string): Promise => { - return containerProviderRegistry.pruneImages(engine); - }); + this.ipcHandle( + 'container-provider-registry:pruneImages', + async (_listener, engine: string, all: boolean): Promise => { + return containerProviderRegistry.pruneImages(engine, all); + }, + ); this.ipcHandle( 'container-provider-registry:restartContainer', diff --git a/packages/preload/src/index.ts b/packages/preload/src/index.ts index 4e2c4583f..33381b53b 100644 --- a/packages/preload/src/index.ts +++ b/packages/preload/src/index.ts @@ -2155,8 +2155,8 @@ export function initExposure(): void { return ipcInvoke('container-provider-registry:pruneVolumes', engine); }); - contextBridge.exposeInMainWorld('pruneImages', async (engine: string): Promise => { - return ipcInvoke('container-provider-registry:pruneImages', engine); + contextBridge.exposeInMainWorld('pruneImages', async (engine: string, all = true): Promise => { + return ipcInvoke('container-provider-registry:pruneImages', engine, all); }); contextBridge.exposeInMainWorld('getOsPlatform', async (): Promise => {