From cc8255358f3e893b4baff61a48b1e06ec2979de1 Mon Sep 17 00:00:00 2001 From: Florent Benoit Date: Wed, 9 Aug 2023 14:58:51 +0200 Subject: [PATCH] feat(api): add listContainers method using Podman API (and not Docker API) related to https://github.com/containers/podman-desktop/issues/3376 Signed-off-by: Florent Benoit --- .../plugin/dockerode/libpod-dockerode.spec.ts | 50 ++++++++++++++++++- .../src/plugin/dockerode/libpod-dockerode.ts | 35 +++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/packages/main/src/plugin/dockerode/libpod-dockerode.spec.ts b/packages/main/src/plugin/dockerode/libpod-dockerode.spec.ts index df1817936babf..6c82ae70e24c2 100644 --- a/packages/main/src/plugin/dockerode/libpod-dockerode.spec.ts +++ b/packages/main/src/plugin/dockerode/libpod-dockerode.spec.ts @@ -16,7 +16,9 @@ * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ -import { beforeAll, test } from 'vitest'; +/* eslint-disable no-null/no-null */ + +import { beforeAll, expect, test } from 'vitest'; import { type LibPod, LibpodDockerode } from '/@/plugin/dockerode/libpod-dockerode.js'; import Dockerode from 'dockerode'; import nock from 'nock'; @@ -43,3 +45,49 @@ test('Check force is given with remove pod options', async () => { const api = new Dockerode({ protocol: 'http', host: 'localhost' }); await (api as unknown as LibPod).removePod('dummy', { force: true }); }); + +test('Check list of containers using Podman API', async () => { + const jsonContainers = [ + { + AutoRemove: false, + Command: ['httpd-foreground'], + Created: '2023-08-09T13:49:31.12068064+02:00', + CreatedAt: '', + Exited: false, + ExitedAt: 1691582587, + ExitCode: 0, + Id: '37a54a845ef27a212634ef00c994c0793b5f19ec16853d606beb1c929461c1cd', + Image: 'docker.io/library/httpd:latest', + ImageID: '911d72fc5020723f0c003a134a8d2f062b4aea884474a11d1db7dcd28ce61d6a', + IsInfra: false, + Labels: null, + Mounts: [], + Names: ['gallant_solomon'], + Namespaces: {}, + Networks: ['podman'], + Pid: 1738, + Pod: '', + PodName: '', + Ports: [ + { + host_ip: '', + container_port: 80, + host_port: 9090, + range: 1, + protocol: 'tcp', + }, + ], + Size: null, + StartedAt: 1691585124, + State: 'running', + Status: '', + }, + ]; + + nock('http://localhost').get('/v4.2.0/libpod/containers/json').reply(200, jsonContainers); + const api = new Dockerode({ protocol: 'http', host: 'localhost' }); + const listOfContainers = await (api as unknown as LibPod).listPodmanContainers(); + expect(listOfContainers.length).toBe(1); + const firstContainer = listOfContainers[0]; + expect(firstContainer.Id).toBe('37a54a845ef27a212634ef00c994c0793b5f19ec16853d606beb1c929461c1cd'); +}); diff --git a/packages/main/src/plugin/dockerode/libpod-dockerode.ts b/packages/main/src/plugin/dockerode/libpod-dockerode.ts index 382c79401dcd0..16cdb3630f506 100644 --- a/packages/main/src/plugin/dockerode/libpod-dockerode.ts +++ b/packages/main/src/plugin/dockerode/libpod-dockerode.ts @@ -99,11 +99,25 @@ export interface PodRemoveOptions { force: boolean; } +export interface PodmanContainerInfo { + Id: string; + Names: string[]; + ImageID: string; + Image: string; + Created: string; + State: string; + StartedAt: number; + Command: string[]; + Labels: { [label: string]: string }; + Ports: { host_ip: string; container_port: number; host_port: number; range?: string; protocol: string }[]; +} + // API of libpod that we want to expose on our side export interface LibPod { createPod(podOptions: PodCreateOptions): Promise<{ Id: string }>; createPodmanContainer(containerCreateOptions: ContainerCreateOptions): Promise<{ Id: string; Warnings: string[] }>; listPods(): Promise; + listPodmanContainers(opts?: { all: boolean }): Promise; prunePods(): Promise; getPodInspect(podId: string): Promise; startPod(podId: string): Promise; @@ -122,6 +136,27 @@ export class LibpodDockerode { enhancePrototypeWithLibPod() { // eslint-disable-next-line @typescript-eslint/no-explicit-any const prototypeOfDockerode = Dockerode.prototype as any; + // add listPodmanContainers + prototypeOfDockerode.listPodmanContainers = function (opts?: { all: boolean }) { + const optsf = { + path: '/v4.2.0/libpod/containers/json', + method: 'GET', + options: opts, + statusCodes: { + 200: true, + 400: 'bad parameter', + 500: 'server error', + }, + }; + return new Promise((resolve, reject) => { + this.modem.dial(optsf, (err: unknown, data: unknown) => { + if (err) { + return reject(err); + } + resolve(data); + }); + }); + }; // add createPodmanContainer prototypeOfDockerode.createPodmanContainer = function (containerCreateOptions: ContainerCreateOptions) {