Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding optional abort controller to dockerode api #4364

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
78 changes: 56 additions & 22 deletions packages/main/src/plugin/container-registry.ts
Expand Up @@ -272,7 +272,7 @@ export class ContainerProviderRegistry {
}

// do not use inspect information
async listSimpleContainers(): Promise<SimpleContainerInfo[]> {
async listSimpleContainers(abortController?: AbortController): Promise<SimpleContainerInfo[]> {
let telemetryOptions = {};
const containers = await Promise.all(
Array.from(this.internalProviders.values()).map(async provider => {
Expand All @@ -282,7 +282,7 @@ export class ContainerProviderRegistry {
return [];
}

const containers = await providerApi.listContainers({ all: true });
const containers = await providerApi.listContainers({ all: true, abortSignal: abortController?.signal });
return Promise.all(
containers.map(async container => {
const containerInfo: SimpleContainerInfo = {
Expand Down Expand Up @@ -311,9 +311,13 @@ export class ContainerProviderRegistry {
}

// listSimpleContainers by matching label and key
async listSimpleContainersByLabel(label: string, key: string): Promise<SimpleContainerInfo[]> {
async listSimpleContainersByLabel(
label: string,
key: string,
abortController?: AbortController,
): Promise<SimpleContainerInfo[]> {
// Get all the containers using listSimpleContainers
const containers = await this.listSimpleContainers();
const containers = await this.listSimpleContainers(abortController);

// Find all the containers that match the label + key
return containers.filter(container => {
Expand Down Expand Up @@ -800,10 +804,10 @@ export class ContainerProviderRegistry {
return this.getMatchingEngine(engineId).getImage(imageId);
}

async stopContainer(engineId: string, id: string): Promise<void> {
async stopContainer(engineId: string, id: string, abortController?: AbortController): Promise<void> {
let telemetryOptions = {};
try {
return this.getMatchingContainer(engineId, id).stop();
return this.getMatchingContainer(engineId, id).stop({ abortSignal: abortController?.signal });
} catch (error) {
telemetryOptions = { error: error };
throw error;
Expand Down Expand Up @@ -856,13 +860,17 @@ export class ContainerProviderRegistry {
imageTag: string,
callback: (name: string, data: string) => void,
authInfo?: containerDesktopAPI.ContainerAuthInfo,
abortController?: AbortController,
): Promise<void> {
let telemetryOptions = {};
try {
const engine = this.getMatchingEngine(engineId);
const image = engine.getImage(imageTag);
const authconfig = authInfo || this.imageRegistry.getAuthconfigForImage(imageTag);
const pushStream = await image.push({ authconfig });
const pushStream = await image.push({
authconfig,
abortSignal: abortController?.signal,
});
pushStream.on('end', () => {
callback('end', '');
});
Expand Down Expand Up @@ -890,13 +898,15 @@ export class ContainerProviderRegistry {
providerContainerConnectionInfo: ProviderContainerConnectionInfo | containerDesktopAPI.ContainerProviderConnection,
imageName: string,
callback: (event: PullEvent) => void,
abortController?: AbortController,
): Promise<void> {
let telemetryOptions = {};
try {
const authconfig = this.imageRegistry.getAuthconfigForImage(imageName);
const matchingEngine = this.getMatchingEngineFromConnection(providerContainerConnectionInfo);
const pullStream = await matchingEngine.pull(imageName, {
authconfig,
abortSignal: abortController?.signal,
});
// eslint-disable-next-line @typescript-eslint/ban-types
let resolve: () => void;
Expand Down Expand Up @@ -971,11 +981,11 @@ export class ContainerProviderRegistry {
}
}

async deleteContainer(engineId: string, id: string): Promise<void> {
async deleteContainer(engineId: string, id: string, abortController?: AbortController): Promise<void> {
let telemetryOptions = {};
try {
// use force to delete it even it is running
return this.getMatchingContainer(engineId, id).remove({ force: true });
return this.getMatchingContainer(engineId, id).remove({ force: true, abortSignal: abortController?.signal });
} catch (error) {
telemetryOptions = { error: error };
throw error;
Expand All @@ -984,7 +994,7 @@ export class ContainerProviderRegistry {
}
}

async startContainer(engineId: string, id: string): Promise<void> {
async startContainer(engineId: string, id: string, abortController?: AbortController): Promise<void> {
let telemetryOptions = {};
try {
const engine = this.internalProviders.get(engineId);
Expand All @@ -993,8 +1003,8 @@ export class ContainerProviderRegistry {
if (engine) {
await this.attachToContainer(engine, container);
}

return container.start();
// see https://github.com/containers/podman-desktop/issues/4363
axel7083 marked this conversation as resolved.
Show resolved Hide resolved
return container.start({ abortSignal: abortController?.signal } as unknown as Dockerode.ContainerStartOptions);
} catch (error) {
telemetryOptions = { error: error };
throw error;
Expand Down Expand Up @@ -1166,7 +1176,7 @@ export class ContainerProviderRegistry {
}
}

async restartContainer(engineId: string, id: string): Promise<void> {
async restartContainer(engineId: string, id: string, abortController?: AbortController): Promise<void> {
let telemetryOptions = {};
try {
const engine = this.internalProviders.get(engineId);
Expand All @@ -1176,7 +1186,7 @@ export class ContainerProviderRegistry {
await this.attachToContainer(engine, container);
}

return container.restart();
return container.restart({ abortSignal: abortController?.signal });
} catch (error) {
telemetryOptions = { error: error };
throw error;
Expand All @@ -1188,11 +1198,16 @@ export class ContainerProviderRegistry {
// Find all containers that match the against the given project name to
// the label com.docker.compose.project (for example)
// and then restart all the containers that have the following label AND key
async restartContainersByLabel(engineId: string, label: string, key: string): Promise<void> {
async restartContainersByLabel(
engineId: string,
label: string,
key: string,
abortController?: AbortController,
): Promise<void> {
let telemetryOptions = {};
try {
// Get all the containers using listSimpleContainers
const containers = await this.listSimpleContainers();
const containers = await this.listSimpleContainers(abortController);

// Find all the containers that are using projectLabel and match the projectName
const containersMatchingProject = containers.filter(container => {
Expand Down Expand Up @@ -1239,7 +1254,12 @@ export class ContainerProviderRegistry {
}

// Stop containers that match a label + key
async stopContainersByLabel(engineId: string, label: string, key: string): Promise<void> {
async stopContainersByLabel(
engineId: string,
label: string,
key: string,
abortController?: AbortController,
): Promise<void> {
let telemetryOptions = {};
try {
// Get all the containers using listSimpleContainers
Expand All @@ -1254,7 +1274,7 @@ export class ContainerProviderRegistry {
const containerIds = containersMatchingProject.map(container => container.Id);

// Stop all the containers
await Promise.all(containerIds.map(containerId => this.stopContainer(engineId, containerId)));
await Promise.all(containerIds.map(containerId => this.stopContainer(engineId, containerId, abortController)));
} catch (error) {
telemetryOptions = { error: error };
throw error;
Expand All @@ -1264,7 +1284,12 @@ export class ContainerProviderRegistry {
}

// Delete all containers that match a certain label and key
async deleteContainersByLabel(engineId: string, label: string, key: string): Promise<void> {
async deleteContainersByLabel(
engineId: string,
label: string,
key: string,
abortController?: AbortController,
): Promise<void> {
let telemetryOptions = {};
try {
// Get all the containers using listSimpleContainers
Expand All @@ -1277,7 +1302,7 @@ export class ContainerProviderRegistry {
const containerIds = containersMatchingProject.map(container => container.Id);

// Delete all the containers in containerIds
await Promise.all(containerIds.map(containerId => this.deleteContainer(engineId, containerId)));
await Promise.all(containerIds.map(containerId => this.deleteContainer(engineId, containerId, abortController)));
} catch (error) {
telemetryOptions = { error: error };
throw error;
Expand All @@ -1286,7 +1311,12 @@ export class ContainerProviderRegistry {
}
}

async logsContainer(engineId: string, id: string, callback: (name: string, data: string) => void): Promise<void> {
async logsContainer(
engineId: string,
id: string,
callback: (name: string, data: string) => void,
abortController?: AbortController,
): Promise<void> {
let telemetryOptions = {};
let firstMessage = true;
const container = this.getMatchingContainer(engineId, id);
Expand All @@ -1295,6 +1325,7 @@ export class ContainerProviderRegistry {
follow: true,
stdout: true,
stderr: true,
abortSignal: abortController?.signal,
})
.then(containerStream => {
containerStream.on('end', () => {
Expand All @@ -1321,6 +1352,7 @@ export class ContainerProviderRegistry {
command: string[],
onStdout: (data: Buffer) => void,
onStderr: (data: Buffer) => void,
abortController?: AbortController,
): Promise<void> {
const container = this.getMatchingContainer(engineId, id);

Expand All @@ -1332,7 +1364,7 @@ export class ContainerProviderRegistry {
Tty: false,
});

const execStream = await exec.start({ hijack: true, stdin: false });
const execStream = await exec.start({ hijack: true, stdin: false, abortSignal: abortController?.signal });

const wrappedAsStream = (redirect: (data: Buffer) => void): Writable => {
return new Writable({
Expand Down Expand Up @@ -1851,6 +1883,7 @@ export class ContainerProviderRegistry {
imageName: string,
selectedProvider: ProviderContainerConnectionInfo,
eventCollect: (eventName: 'stream' | 'error' | 'finish', data: string) => void,
abortController?: AbortController,
): Promise<unknown> {
let telemetryOptions = {};
try {
Expand Down Expand Up @@ -1882,6 +1915,7 @@ export class ContainerProviderRegistry {
registryconfig,
dockerfile: relativeContainerfilePath,
t: imageName,
abortSignal: abortController?.signal,
})) as unknown as Stream;
} catch (error: unknown) {
console.log('error in buildImage', error);
Expand Down