Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions extensions/vscode-containers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
"command": "vscode-containers.containers.composeGroup.logs",
"when": "config.containers.containers.groupBy == 'Compose Project Name'"
},
{
"command": "vscode-containers.containers.composeGroup.pull",
"when": "config.containers.containers.groupBy == 'Compose Project Name'"
},
Comment on lines +82 to +85

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compose groups represent a compose project that is already running. I am not sure that having a pull command for that is as useful as having the other one, which is for compose files. Matt Hernandez (@fiveisprime) any thoughts?

{
"command": "vscode-containers.containers.composeGroup.start",
"when": "config.containers.containers.groupBy == 'Compose Project Name'"
Expand All @@ -99,6 +103,10 @@
"command": "vscode-containers.compose.down",
"when": "isWorkspaceTrusted"
},
{
"command": "vscode-containers.compose.pull",
"when": "isWorkspaceTrusted"
},
{
"command": "vscode-containers.compose.restart",
"when": "isWorkspaceTrusted"
Expand Down Expand Up @@ -175,6 +183,11 @@
"command": "vscode-containers.compose.down",
"group": "containers"
},
{
"when": "isWorkspaceTrusted && editorLangId == dockercompose",
"command": "vscode-containers.compose.pull",
"group": "containers"
},
{
"when": "isWorkspaceTrusted && editorLangId == dockercompose",
"command": "vscode-containers.compose.restart",
Expand Down Expand Up @@ -212,6 +225,11 @@
"command": "vscode-containers.compose.down",
"group": "containers"
},
{
"when": "isWorkspaceTrusted && resourceLangId == dockercompose",
"command": "vscode-containers.compose.pull",
"group": "containers"
},
{
"when": "isWorkspaceTrusted && resourceLangId == dockercompose",
"command": "vscode-containers.compose.restart",
Expand Down Expand Up @@ -442,15 +460,20 @@
"group": "composeGroup_1_general@1"
},
{
"command": "vscode-containers.containers.composeGroup.start",
"command": "vscode-containers.containers.composeGroup.pull",
"when": "view == vscode-containers.views.containers && viewItem =~ /composeGroup$/i",
"group": "composeGroup_1_general@2"
},
{
"command": "vscode-containers.containers.composeGroup.stop",
"command": "vscode-containers.containers.composeGroup.start",
"when": "view == vscode-containers.views.containers && viewItem =~ /composeGroup$/i",
"group": "composeGroup_1_general@3"
},
{
"command": "vscode-containers.containers.composeGroup.stop",
"when": "view == vscode-containers.views.containers && viewItem =~ /composeGroup$/i",
"group": "composeGroup_1_general@4"
},
{
"command": "vscode-containers.containers.composeGroup.restart",
"when": "view == vscode-containers.views.containers && viewItem =~ /composeGroup$/i",
Expand Down Expand Up @@ -2633,6 +2656,11 @@
"title": "%vscode-containers.commands.compose.down%",
"category": "%vscode-containers.commands.category.containersGeneric%"
},
{
"command": "vscode-containers.compose.pull",
"title": "%vscode-containers.commands.compose.pull%",
"category": "%vscode-containers.commands.category.containersGeneric%"
},
{
"command": "vscode-containers.compose.restart",
"title": "%vscode-containers.commands.compose.restart%",
Expand Down Expand Up @@ -2758,6 +2786,11 @@
"title": "%vscode-containers.commands.containers.composeGroup.logs%",
"category": "%vscode-containers.commands.category.containers%"
},
{
"command": "vscode-containers.containers.composeGroup.pull",
"title": "%vscode-containers.commands.containers.composeGroup.pull%",
"category": "%vscode-containers.commands.category.containers%"
},
{
"command": "vscode-containers.containers.composeGroup.start",
"title": "%vscode-containers.commands.containers.composeGroup.start%",
Expand Down
2 changes: 2 additions & 0 deletions extensions/vscode-containers/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
"vscode-containers.config.containers.orchestratorClient.finchCompose": "Finch Compose",
"vscode-containers.config.deprecated": "This setting has been deprecated and will be removed in a future release.",
"vscode-containers.commands.compose.down": "Compose Down",
"vscode-containers.commands.compose.pull": "Compose Pull",
"vscode-containers.commands.compose.restart": "Compose Restart",
"vscode-containers.commands.compose.up": "Compose Up",
"vscode-containers.commands.compose.up.subset": "Compose Up - Select Services",
Expand All @@ -251,6 +252,7 @@
"vscode-containers.commands.containers.stats": "Stats",
"vscode-containers.commands.containers.viewLogs": "View Logs",
"vscode-containers.commands.containers.composeGroup.logs": "Compose Logs",
"vscode-containers.commands.containers.composeGroup.pull": "Compose Pull",
"vscode-containers.commands.containers.composeGroup.start": "Compose Start",
"vscode-containers.commands.containers.composeGroup.stop": "Compose Stop",
"vscode-containers.commands.containers.composeGroup.restart": "Compose Restart",
Expand Down
26 changes: 16 additions & 10 deletions extensions/vscode-containers/src/commands/compose/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { quickPickWorkspaceFolder } from '../../utils/quickPickWorkspaceFolder';
import { selectComposeCommand } from '../selectCommandTemplate';
import { getComposeProfileList, getComposeProfilesOrServices, getComposeServiceList, getDefaultCommandComposeProfilesOrServices } from './getComposeSubsetList';

async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSubset' | 'downSubset')[], message: string, dockerComposeFileUri?: vscode.Uri | string, selectedComposeFileUris?: vscode.Uri[], preselectedServices?: string[], preselectedProfiles?: string[]): Promise<void> {
async function compose(context: IActionContext, commands: ('up' | 'down' | 'pull' | 'upSubset' | 'downSubset')[], message: string, dockerComposeFileUri?: vscode.Uri | string, selectedComposeFileUris?: vscode.Uri[], preselectedServices?: string[], preselectedProfiles?: string[]): Promise<void> {
if (!vscode.workspace.isTrusted) {
throw new UserCancelledError('enforceTrust');
}
Expand Down Expand Up @@ -55,14 +55,17 @@ async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSu
}

for (const item of selectedItems) {
let terminalCommand = await selectComposeCommand(
context,
folder,
command,
item?.relativeFilePath,
detached,
build
);
const client = await ext.orchestratorManager.getClient();
let terminalCommand = command === 'pull'
? await client.pull({ files: item?.relativeFilePath ? [item.relativeFilePath] : undefined })
: await selectComposeCommand(
context,
folder,
command,
item?.relativeFilePath,
detached,
build
);

if (!terminalCommand.args?.length) {
// Add the service list if needed
Expand All @@ -73,7 +76,6 @@ async function compose(context: IActionContext, commands: ('up' | 'down' | 'upSu
terminalCommand = await addDefaultCommandServicesOrProfilesIfNeeded(context, folder, terminalCommand, preselectedServices, preselectedProfiles);
}

const client = await ext.orchestratorManager.getClient();
const taskCRF = new TaskCommandRunnerFactory({
taskName: client.displayName,
workspaceFolder: folder,
Expand All @@ -98,6 +100,10 @@ export async function composeDown(context: IActionContext, dockerComposeFileUri?
return await compose(context, ['down'], vscode.l10n.t('Choose compose file to take down'), dockerComposeFileUri, selectedComposeFileUris);
}

export async function composePull(context: IActionContext, dockerComposeFileUri?: vscode.Uri | string, selectedComposeFileUris?: vscode.Uri[]): Promise<void> {
return await compose(context, ['pull'], vscode.l10n.t('Choose compose file whose images to pull'), dockerComposeFileUri, selectedComposeFileUris);
}

export async function composeDownSubset(context: IActionContext, dockerComposeFileUri?: vscode.Uri | string, selectedComposeFileUris?: vscode.Uri[], preselectedServices?: string[], preselectedProfiles?: string[]): Promise<void> {
return await compose(context, ['downSubset'], vscode.l10n.t('Choose compose file to take down'), dockerComposeFileUri, selectedComposeFileUris, preselectedServices, preselectedProfiles);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/

import { IActionContext } from '@microsoft/vscode-azext-utils';
import { CommonOrchestratorCommandOptions, IContainerOrchestratorClient, LogsCommandOptions, VoidCommandResponse } from '@microsoft/vscode-container-client';
import { CommonOrchestratorCommandOptions, IContainerOrchestratorClient, LogsCommandOptions, VoidCommandResponse } from '@microsoft/vscode-container-client';
import * as path from 'path';
import { l10n, Uri, workspace } from 'vscode';
import { ext } from '../../extensionVariables';
import { ext } from '../../extensionVariables';
import { TaskCommandRunnerFactory } from '../../runtimes/runners/TaskCommandRunnerFactory';
import { ContainerGroupTreeItem } from '../../tree/containers/ContainerGroupTreeItem';
import { ContainerTreeItem } from '../../tree/containers/ContainerTreeItem';
Expand Down Expand Up @@ -41,9 +41,13 @@ export async function composeGroupRestart(context: IActionContext, node: Contain
return composeGroup(context, (client, options) => client.restart(options), node);
}

export async function composeGroupDown(context: IActionContext, node: ContainerGroupTreeItem): Promise<void> {
export async function composeGroupDown(context: IActionContext, node: ContainerGroupTreeItem): Promise<void> {
return composeGroup(context, (client, options) => client.down(options), node);
}
}

export async function composeGroupPull(context: IActionContext, node: ContainerGroupTreeItem): Promise<void> {
return composeGroup(context, (client, options) => client.pull(options), node);
}

type AdditionalOptions<TOptions extends CommonOrchestratorCommandOptions> = Omit<TOptions, keyof CommonOrchestratorCommandOptions>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import { scaffold } from "../scaffolding/scaffold";
import { scaffoldCompose } from "../scaffolding/scaffoldCompose";
import { scaffoldDebugConfig } from "../scaffolding/scaffoldDebugConfig";
import { chooseContainerRuntime } from "./chooseContainerRuntime";
import { composeDown, composeDownSubset, composeRestart, composeUp, composeUpSubset } from "./compose/compose";
import { composeDown, composeDownSubset, composePull, composeRestart, composeUp, composeUpSubset } from "./compose/compose";
import { askCopilot } from "./containers/askCopilot";
import { attachShellContainer } from "./containers/attachShellContainer";
import { browseContainer } from "./containers/browseContainer";
import { composeGroupDown, composeGroupLogs, composeGroupRestart, composeGroupStart, composeGroupStop } from "./containers/composeGroup";
import { composeGroupDown, composeGroupLogs, composeGroupPull, composeGroupRestart, composeGroupStart, composeGroupStop } from "./containers/composeGroup";
import { configureContainersExplorer } from "./containers/configureContainersExplorer";
import { downloadContainerFile } from "./containers/files/downloadContainerFile";
import { openContainerFile } from "./containers/files/openContainerFile";
Expand Down Expand Up @@ -120,6 +120,7 @@ export function registerCommands(): void {
registerWorkspaceCommand('vscode-containers.debugging.initializeForDebugging', scaffoldDebugConfig);

registerWorkspaceCommand('vscode-containers.compose.down', composeDown);
registerWorkspaceCommand('vscode-containers.compose.pull', composePull);
registerWorkspaceCommand('vscode-containers.compose.restart', composeRestart);
registerWorkspaceCommand('vscode-containers.compose.up', composeUp);
registerWorkspaceCommand('vscode-containers.compose.up.subset', composeUpSubset);
Expand All @@ -144,6 +145,7 @@ export function registerCommands(): void {
registerWorkspaceCommand('vscode-containers.containers.stats', stats);
registerWorkspaceCommand('vscode-containers.containers.viewLogs', viewContainerLogs);
registerWorkspaceCommand('vscode-containers.containers.composeGroup.logs', composeGroupLogs);
registerWorkspaceCommand('vscode-containers.containers.composeGroup.pull', composeGroupPull);
registerWorkspaceCommand('vscode-containers.containers.composeGroup.start', composeGroupStart);
registerWorkspaceCommand('vscode-containers.containers.composeGroup.stop', composeGroupStop);
registerWorkspaceCommand('vscode-containers.containers.composeGroup.restart', composeGroupRestart);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { DockerComposeClient, IContainerOrchestratorClient } from '@microsoft/vscode-container-client';
import { DockerComposeClient, IContainerOrchestratorClient } from '@microsoft/vscode-container-client';
import * as vscode from 'vscode';
import { configPrefix } from '../constants';
import { RuntimeManager } from './RuntimeManager';
Expand Down Expand Up @@ -44,6 +44,6 @@ interface ComposeV2ableOrchestratorClient extends IContainerOrchestratorClient {
composeV2: boolean;
}

export function isComposeV2ableOrchestratorClient(maybeClient: IContainerOrchestratorClient): maybeClient is ComposeV2ableOrchestratorClient {
return 'composeV2' in maybeClient && typeof (maybeClient as ComposeV2ableOrchestratorClient).composeV2 === 'boolean';
}
export function isComposeV2ableOrchestratorClient(maybeClient: IContainerOrchestratorClient): maybeClient is ComposeV2ableOrchestratorClient {
return 'composeV2' in maybeClient && typeof (maybeClient as ComposeV2ableOrchestratorClient).composeV2 === 'boolean';
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import type {
ConfigItem,
DownCommandOptions,
IContainerOrchestratorClient,
LogsCommandOptions,
LogsCommandOptions,
PullCommandOptions,
RestartCommandOptions,
StartCommandOptions,
StopCommandOptions,
Expand Down Expand Up @@ -144,9 +145,30 @@ export abstract class DockerComposeClientBase extends ConfigurableClient impleme
return this.makeVoidCommandResponse(this.getDownCommandArgs(options));
}

//#endregion Down command

//#region Start command
//#endregion Down command

//#region Pull command

protected getPullCommandArgs(options: PullCommandOptions): CommandLineArgs {
return composeArgs(
withComposeArg(this.composeV2),
withCommonOrchestratorArgs(options),
withArg('pull'),
)();
}

/**
* Generates the necessary information for pulling service images with Docker Compose
* @param options Standard orchestrator pull command options
* @returns A CommandResponse indicating how to run a Docker Compose pull command
*/
public pull(options: PullCommandOptions): Promise<VoidCommandResponse> {
return this.makeVoidCommandResponse(this.getPullCommandArgs(options));
}

//#endregion Pull command

//#region Start command

protected getStartCommandArgs(options: StartCommandOptions): CommandLineArgs {
return composeArgs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ type DownCommand = {
down(options: DownCommandOptions): Promise<VoidCommandResponse>;
};

// Pull command types
export type PullCommandOptions = CommonOrchestratorCommandOptions;

type PullCommand = {
/**
* Generate a {@link VoidCommandResponse} for pulling service images with a container orchestrator
* @param options Command options
*/
pull(options: PullCommandOptions): Promise<VoidCommandResponse>;
};

// Start command types
export type StartCommandOptions = CommonOrchestratorCommandOptions & {
/**
Expand Down Expand Up @@ -247,6 +258,7 @@ export interface IContainerOrchestratorClient extends
CheckOrchestratorInstallCommand,
UpCommand,
DownCommand,
PullCommand,
Comment thread
bwateratmsft marked this conversation as resolved.
StartCommand,
StopCommand,
RestartCommand,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('(unit) DockerComposeClient', () => {
const client = new DockerComposeClient();
client.composeV2 = false;

it('Should produce the expected lack of quoting/escaping customOptions', async () => {
it('Should produce the expected lack of quoting/escaping customOptions', async () => {
const options: UpCommandOptions = {
...commonOptions,
detached: true,
Expand All @@ -40,5 +40,15 @@ describe('(unit) DockerComposeClient', () => {
expect(bashQuoted).to.deep.equal(['--file', '\'docker-compose.yml\'', 'up', '--detach', '--build', '--timeout 10 --wait']);
expect(noShellQuotedWindows).to.deep.equal(['--file', '"docker-compose.yml"', 'up', '--detach', '--build', '--timeout 10 --wait']);
expect(noShellQuotedLinux).to.deep.equal(['--file', 'docker-compose.yml', 'up', '--detach', '--build', '--timeout 10 --wait']);
});
});
});

it('Should produce the expected compose pull command', async () => {
const commandResponse = await client.pull(commonOptions);

expect(new NoShell(false).quote(commandResponse.args)).to.deep.equal([
'--file',
'docker-compose.yml',
'pull',
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,11 @@ describe('(unit) NerdctlComposeClient', () => {
expect(args).to.deep.equal(['compose', '--file', 'docker-compose.yml', 'down', '--volumes']);
expect(args).to.not.include('--timeout');
});

it('Should pull all service images with the V2 compose syntax', async () => {
const response = await client.pull(commonOptions);
const args = new NoShell(false).quote(response.args);

expect(args).to.deep.equal(['compose', '--file', 'docker-compose.yml', 'pull']);
});
});