diff --git a/commands/azureCommands/delete-registry.ts b/commands/azureCommands/delete-registry.ts index 3b2918c7a8..5051bcf8a9 100644 --- a/commands/azureCommands/delete-registry.ts +++ b/commands/azureCommands/delete-registry.ts @@ -20,7 +20,7 @@ export async function deleteAzureRegistry(context?: AzureRegistryNode): Promise< if (context) { registry = context.registry; } else { - registry = await quickPickACRRegistry(false, 'Select the registry you want to delete'); + registry = await quickPickACRRegistry(false, undefined, 'Select the registry you want to delete'); } const shouldDelete = await confirmUserIntent(`Are you sure you want to delete ${registry.name} and its associated images?`); if (shouldDelete) { diff --git a/commands/azureCommands/pull-from-azure.ts b/commands/azureCommands/pull-from-azure.ts index b2c2bd91dd..666c384510 100644 --- a/commands/azureCommands/pull-from-azure.ts +++ b/commands/azureCommands/pull-from-azure.ts @@ -9,88 +9,91 @@ import { exec } from 'child_process'; import * as fse from 'fs-extra'; import * as path from "path"; import vscode = require('vscode'); -import { callWithTelemetryAndErrorHandling, IActionContext, parseError } from 'vscode-azureextensionui'; -import { UserCancelledError } from '../../explorer/deploy/wizard'; +import { callWithTelemetryAndErrorHandling, IActionContext } from 'vscode-azureextensionui'; import { AzureImageTagNode, AzureRepositoryNode } from '../../explorer/models/azureRegistryNodes'; import { ext } from '../../extensionVariables'; import * as acrTools from '../../utils/Azure/acrTools'; import { AzureImage } from "../../utils/Azure/models/image"; import { Repository } from "../../utils/Azure/models/repository"; -import * as quickPicks from '../utils/quick-pick-azure'; +import { quickPickACRImage, quickPickACRRegistry, quickPickACRRepository } from '../utils/quick-pick-azure'; + +export async function pullRepoFromAzure(context?: AzureRepositoryNode): Promise { + await pullFromAzure(context, true); +} + +export async function pullImageFromAzure(context?: AzureImageTagNode): Promise { + await pullFromAzure(context, false); +} /* Pulls an image from Azure. The context is the image node the user has right clicked on */ -export async function pullFromAzure(context?: AzureImageTagNode | AzureRepositoryNode): Promise { - let registryName: string; +async function pullFromAzure(context: AzureImageTagNode | AzureRepositoryNode, pullAll: boolean): Promise { let registry: Registry; - let imageName: string; + let imageRequest: string; if (context) { // Right Click - registryName = context.registry.loginServer; registry = context.registry; if (context instanceof AzureImageTagNode) { // Right Click on AzureImageNode - imageName = context.label; + imageRequest = context.label; } else if (context instanceof AzureRepositoryNode) { // Right Click on AzureRepositoryNode - imageName = `${context.label} -a`; // Pull all images in repository + imageRequest = `${context.label} -a`; // Pull all images in repository } else { assert.fail(`Unexpected node type`); } } else { // Command Palette - registry = await quickPicks.quickPickACRRegistry(); - registryName = registry.loginServer; - const repository: Repository = await quickPicks.quickPickACRRepository(registry, 'Select the repository of the image you want to pull'); - const image: AzureImage = await quickPicks.quickPickACRImage(repository, 'Select the image you want to pull'); - imageName = `${repository.name}:${image.tag}`; + registry = await quickPickACRRegistry(); + const repository: Repository = await quickPickACRRepository(registry, 'Select the repository of the image you want to pull.'); + if (pullAll) { + imageRequest = `${repository.name} -a`; + } else { + const image: AzureImage = await quickPickACRImage(repository, 'Select the image you want to pull'); + imageRequest = image.toString(); + } } // Using loginCredentials function to get the username and password. This takes care of all users, even if they don't have the Azure CLI - const credentials = await acrTools.getLoginCredentials(registry); - const username = credentials.username; - const password = credentials.password; - await pullImage(registryName, imageName, username, password); + const { username, password } = await acrTools.getLoginCredentials(registry); + await pullImage(registry.loginServer, imageRequest, username, password); } -async function pullImage(registryName: string, imageName: string, username: string, password: string): Promise { - // Check if user is logged into Docker and send appropriate commands to terminal - let result = await isLoggedIntoDocker(registryName); - if (!result.loggedIn) { // If not logged in to Docker - let login: vscode.MessageItem = { title: 'Log in to Docker CLI' }; - let msg = `You are not currently logged in to "${registryName}" in the Docker CLI.`; - let response = await vscode.window.showErrorMessage(msg, login) - if (response !== login) { - throw new UserCancelledError(msg); - } +async function pullImage(loginServer: string, imageRequest: string, username: string, password: string): Promise { + // We can't know if the key is still active. So we login into Docker and send appropriate commands to terminal + let dockerConfigPath: string = path.join(process.env.HOMEPATH, '.docker', 'config.json'); + + await new Promise((resolve, reject) => { + const dockerLoginCmd = `docker login ${loginServer} --username ${username} --password-stdin`; + let childProcess = exec(dockerLoginCmd, (err, stdout, stderr) => { + ext.outputChannel.append(`${dockerLoginCmd} xxxxxx\n`); + ext.outputChannel.append(stdout); + ext.outputChannel.append(stderr); + if (err && err.message.match(/error storing credentials.*The stub received bad data/)) { + // Temporary work-around for this error- same as Azure CLI + // See https://github.com/Azure/azure-cli/issues/4843 + ext.outputChannel.show(); + reject(new Error(`In order to log in to the Docker CLI using tokens, you currently need to go to \n${dockerConfigPath} and remove "credsStore": "wincred" from the config.json file, then try again. \nDoing this will disable wincred and cause Docker to store credentials directly in the .docker/config.json file. All registries that are currently logged in will be effectly logged out.`)); + } else if (err) { + ext.outputChannel.show(); + reject(err); + } else if (stderr) { + ext.outputChannel.show(); + reject(stderr); + } - await new Promise((resolve, reject) => { - let childProcess = exec(`docker login ${registryName} --username ${username} --password-stdin`, (err, stdout, stderr) => { - ext.outputChannel.append(stdout); - ext.outputChannel.append(stderr); - if (err && err.message.match(/error storing credentials.*The stub received bad data/)) { - // Temporary work-around for this error- same as Azure CLI - // See https://github.com/Azure/azure-cli/issues/4843 - reject(new Error(`In order to log in to the Docker CLI using tokens, you currently need to go to \n${result.configPath} and remove "credsStore": "wincred" from the config.json file, then try again. \nDoing this will disable wincred and cause Docker to store credentials directly in the .docker/config.json file. All registries that are currently logged in will be effectly logged out.`)); - } else if (err) { - reject(err); - } else if (stderr) { - reject(stderr); - } - - resolve(); - }); - - childProcess.stdin.write(password); // Prevents insecure password error - childProcess.stdin.end(); + resolve(); }); - } + + childProcess.stdin.write(password); // Prevents insecure password error + childProcess.stdin.end(); + }); const terminal: vscode.Terminal = ext.terminalProvider.createTerminal("docker pull"); terminal.show(); - terminal.sendText(`docker pull ${registryName}/${imageName}`); + terminal.sendText(`docker pull ${loginServer}/${imageRequest}`); } -async function isLoggedIntoDocker(registryName: string): Promise<{ configPath: string, loggedIn: boolean }> { +async function isLoggedIntoDocker(loginServer: string): Promise<{ configPath: string, loggedIn: boolean }> { let home = process.env.HOMEPATH; let configPath: string = path.join(home, '.docker', 'config.json'); let buffer: Buffer; @@ -100,7 +103,7 @@ async function isLoggedIntoDocker(registryName: string): Promise<{ configPath: s buffer = fse.readFileSync(configPath); }); - let index = buffer.indexOf(registryName); + let index = buffer.indexOf(loginServer); let loggedIn = index >= 0; // Returns -1 if user is not logged into Docker return { configPath, loggedIn }; // Returns object with configuration path and boolean indicating if user was logged in or not } diff --git a/commands/azureCommands/run-task.ts b/commands/azureCommands/run-task.ts index 2d5cee18e1..124e33efc7 100644 --- a/commands/azureCommands/run-task.ts +++ b/commands/azureCommands/run-task.ts @@ -1,5 +1,5 @@ -import { TaskRunRequest } from "azure-arm-containerregistry/lib/models"; import { Registry } from "azure-arm-containerregistry/lib/models"; +import { TaskRunRequest } from "azure-arm-containerregistry/lib/models"; import { ResourceGroup } from "azure-arm-resource/lib/resource/models"; import { Subscription } from "azure-arm-resource/lib/subscription/models"; import vscode = require('vscode'); @@ -29,7 +29,7 @@ export async function runTask(context?: TaskNode): Promise { taskName = context.task.name; } else { // Command Palette subscription = await quickPickSubscription(); - registry = await quickPickACRRegistry(); + registry = await quickPickACRRegistry(false, subscription); resourceGroup = await acrTools.getResourceGroup(registry, subscription); taskName = (await quickPickTask(registry, subscription, resourceGroup)).name; } diff --git a/commands/azureCommands/show-task.ts b/commands/azureCommands/show-task.ts index e515eda150..eedee241d1 100644 --- a/commands/azureCommands/show-task.ts +++ b/commands/azureCommands/show-task.ts @@ -20,7 +20,7 @@ export async function showTaskProperties(context?: TaskNode): Promise { task = context.task.name; } else { // Command palette subscription = await quickPickSubscription(); - registry = await quickPickACRRegistry(); + registry = await quickPickACRRegistry(false, subscription); resourceGroup = await acrTools.getResourceGroup(registry, subscription); task = (await quickPickTask(registry, subscription, resourceGroup)).name; } diff --git a/commands/build-image.ts b/commands/build-image.ts index a999631345..0dfef412dd 100644 --- a/commands/build-image.ts +++ b/commands/build-image.ts @@ -5,73 +5,20 @@ import * as path from "path"; import * as vscode from "vscode"; -import { DialogResponses, IActionContext, UserCancelledError } from "vscode-azureextensionui"; -import { DOCKERFILE_GLOB_PATTERN, YAML_GLOB_PATTERN } from '../dockerExtension'; +import { IActionContext } from "vscode-azureextensionui"; import { delay } from "../explorer/utils/utils"; import { ext } from "../extensionVariables"; import { addImageTaggingTelemetry, getTagFromUserInput } from "./tag-image"; +import { quickPickDockerFileItem } from "./utils/quick-pick-file"; import { quickPickWorkspaceFolder } from "./utils/quickPickWorkspaceFolder"; -async function getFileUris(folder: vscode.WorkspaceFolder, globPattern: string): Promise { - return await vscode.workspace.findFiles(new vscode.RelativePattern(folder, globPattern), undefined, 1000, undefined); -} - -export interface Item extends vscode.QuickPickItem { - relativeFilePath: string; - relativeFolderPath: string; -} - -function createFileItem(rootFolder: vscode.WorkspaceFolder, uri: vscode.Uri): Item { - let relativeFilePath = path.join(".", uri.fsPath.substr(rootFolder.uri.fsPath.length)); - - return { - description: undefined, - relativeFilePath: relativeFilePath, - label: relativeFilePath, - relativeFolderPath: path.dirname(relativeFilePath) - }; -} - -export async function resolveFileItem(rootFolder: vscode.WorkspaceFolder, fileUri: vscode.Uri | undefined, globPattern: string, message: string): Promise { - if (fileUri) { - return createFileItem(rootFolder, fileUri); - } - - let uris: vscode.Uri[] = await getFileUris(rootFolder, globPattern); - - if (!uris || uris.length === 0) { - return undefined; - } else { - let items: Item[] = uris.map(uri => createFileItem(rootFolder, uri)); - if (items.length === 1) { - return items[0]; - } else { - const res: vscode.QuickPickItem = await ext.ui.showQuickPick(items, { placeHolder: message }); - return res; - } - } -} - export async function buildImage(actionContext: IActionContext, dockerFileUri: vscode.Uri | undefined): Promise { const configOptions: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('docker'); const defaultContextPath = configOptions.get('imageBuildContextPath', ''); - let dockerFileItem: Item | undefined; let rootFolder: vscode.WorkspaceFolder = await quickPickWorkspaceFolder('To build Docker files you must first open a folder or workspace in VS Code.'); - while (!dockerFileItem) { - let resolvedItem: Item | undefined = await resolveFileItem(rootFolder, dockerFileUri, DOCKERFILE_GLOB_PATTERN, 'Choose a Dockerfile to build the image.'); - if (resolvedItem) { - dockerFileItem = resolvedItem; - } else { - let msg = "Couldn't find a Dockerfile in your workspace. Would you like to add Docker files to the workspace?"; - actionContext.properties.cancelStep = msg; - await ext.ui.showWarningMessage(msg, DialogResponses.yes, DialogResponses.cancel); - actionContext.properties.cancelStep = undefined; - await vscode.commands.executeCommand('vscode-docker.configure'); - // Try again - } - } + const dockerFileItem = await quickPickDockerFileItem(actionContext, dockerFileUri, rootFolder); let contextPath: string = dockerFileItem.relativeFolderPath; if (defaultContextPath && defaultContextPath !== '') { diff --git a/commands/docker-compose.ts b/commands/docker-compose.ts index 8e8211bf75..ad6f2e3335 100644 --- a/commands/docker-compose.ts +++ b/commands/docker-compose.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; -import { COMPOSE_FILE_GLOB_PATTERN } from '../dockerExtension'; +import { COMPOSE_FILE_GLOB_PATTERN } from '../constants'; import { ext } from '../extensionVariables'; import { quickPickWorkspaceFolder } from './utils/quickPickWorkspaceFolder'; diff --git a/commands/utils/SourceArchiveUtility.ts b/commands/utils/SourceArchiveUtility.ts index cdc848846e..7523aa1985 100644 --- a/commands/utils/SourceArchiveUtility.ts +++ b/commands/utils/SourceArchiveUtility.ts @@ -1,43 +1,42 @@ + import { ContainerRegistryManagementClient } from 'azure-arm-containerregistry/lib/containerRegistryManagementClient'; import { DockerBuildRequest, FileTaskRunRequest, Registry } from 'azure-arm-containerregistry/lib/models'; import { Subscription } from 'azure-arm-resource/lib/subscription/models'; import { BlobService, createBlobServiceWithSas } from "azure-storage"; import * as fse from 'fs-extra'; import * as os from 'os'; +import * as path from 'path'; import * as tar from 'tar'; -import * as url from 'url'; import vscode = require('vscode'); import { IActionContext, IAzureQuickPickItem } from 'vscode-azureextensionui'; import { ext } from '../../extensionVariables'; import { getBlobInfo, getResourceGroupName, streamLogs } from "../../utils/Azure/acrTools"; import { AzureUtilityManager } from '../../utils/azureUtilityManager'; -import { Item } from '../build-image'; import { quickPickACRRegistry, quickPickSubscription } from './quick-pick-azure'; -import { quickPickDockerFileItem, quickPickImageName, quickPickYamlFileItem } from './quick-pick-image'; +import { Item, quickPickDockerFileItem, quickPickYamlFileItem } from './quick-pick-file'; +import { quickPickImageName } from './quick-pick-image'; import { quickPickWorkspaceFolder } from './quickPickWorkspaceFolder'; const idPrecision = 6; const vcsIgnoreList = ['.git', '.gitignore', '.bzr', 'bzrignore', '.hg', '.hgignore', '.svn'] -export type runRequestType = - | 'DockerBuildRequest' - | 'FileTaskRunRequest'; - -export async function scheduleRunRequest(fileUri: vscode.Uri, requestType: runRequestType, actionContext?: IActionContext): Promise { +export async function scheduleRunRequest(fileUri: vscode.Uri, requestType: 'DockerBuildRequest' | 'FileTaskRunRequest', actionContext?: IActionContext): Promise { //Acquire information. let rootFolder: vscode.WorkspaceFolder; let fileItem: Item; + let imageName: string; if (requestType === 'DockerBuildRequest') { rootFolder = await quickPickWorkspaceFolder("To quick build Docker files you must first open a folder or workspace in VS Code."); fileItem = await quickPickDockerFileItem(actionContext, fileUri, rootFolder); + imageName = await quickPickImageName(actionContext, rootFolder, fileItem); } else if (requestType === 'FileTaskRunRequest') { rootFolder = await quickPickWorkspaceFolder("To run a task from a .yaml file you must first open a folder or workspace in VS Code."); - fileItem = await quickPickYamlFileItem(fileUri, rootFolder); + fileItem = await quickPickYamlFileItem(fileUri, rootFolder, "To run a task from a .yaml file you must have yaml file in your VS Code workspace."); } else { throw new Error("Run Request Type Currently not supported."); } const subscription: Subscription = await quickPickSubscription(); - const registry: Registry = await quickPickACRRegistry(true); + const registry: Registry = await quickPickACRRegistry(true, subscription); const osPick = ['Linux', 'Windows'].map(item => >{ label: item, data: item }); const osType: string = (await ext.ui.showQuickPick(osPick, { 'canPickMany': false, 'placeHolder': 'Select image base OS' })).data; @@ -53,7 +52,6 @@ export async function scheduleRunRequest(fileUri: vscode.Uri, requestType: runRe let runRequest: DockerBuildRequest | FileTaskRunRequest; if (requestType === 'DockerBuildRequest') { - const imageName: string = await quickPickImageName(actionContext, rootFolder, fileItem); runRequest = { type: requestType, imageNames: [imageName], @@ -109,6 +107,6 @@ function getTempSourceArchivePath(): string { const id: number = Math.floor(Math.random() * Math.pow(10, idPrecision)); const archive = `sourceArchive${id}.tar.gz`; ext.outputChannel.appendLine(`Setting up temp file with '${archive}'`); - const tarFilePath: string = url.resolve(os.tmpdir(), archive); + const tarFilePath: string = path.join(os.tmpdir(), archive); return tarFilePath; } diff --git a/commands/utils/quick-pick-azure.ts b/commands/utils/quick-pick-azure.ts index 310208ccac..ffa7fcd46f 100644 --- a/commands/utils/quick-pick-azure.ts +++ b/commands/utils/quick-pick-azure.ts @@ -2,8 +2,8 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See LICENSE.md in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Registry } from 'azure-arm-containerregistry/lib/models'; import * as ContainerModels from 'azure-arm-containerregistry/lib/models'; +import { Registry } from 'azure-arm-containerregistry/lib/models'; import { ResourceGroup } from 'azure-arm-resource/lib/resource/models'; import { Location, Subscription } from 'azure-arm-resource/lib/subscription/models'; import * as opn from 'opn'; @@ -45,9 +45,9 @@ export async function quickPickTask(registry: Registry, subscription: Subscripti return desiredTask.data; } -export async function quickPickACRRegistry(canCreateNew: boolean = false, prompt?: string): Promise { +export async function quickPickACRRegistry(canCreateNew: boolean = false, subscription?: Subscription, prompt?: string): Promise { const placeHolder = prompt ? prompt : 'Select registry'; - let registries = await AzureUtilityManager.getInstance().getRegistries(); + let registries = await AzureUtilityManager.getInstance().getRegistries(subscription); let quickPickRegList = registries.map(reg => >{ label: reg.name, data: reg }); let createNewItem: IAzureQuickPickItem = { label: '+ Create new registry', data: undefined }; @@ -144,12 +144,12 @@ export async function confirmUserIntent(yesOrNoPrompt: string): Promise ignoreFocusOut: true, placeHolder: 'Enter "Yes"', value: 'No', - prompt: yesOrNoPrompt + ' Enter yes to continue' + prompt: yesOrNoPrompt }; let answer = await ext.ui.showInputBox(opt); answer = answer.toLowerCase(); if (answer === 'yes') { - return answer === 'yes'; + return true; } else { throw new UserCancelledError(); } diff --git a/commands/utils/quick-pick-file.ts b/commands/utils/quick-pick-file.ts new file mode 100644 index 0000000000..3b741bd1b2 --- /dev/null +++ b/commands/utils/quick-pick-file.ts @@ -0,0 +1,77 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE.md in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from "path"; +import vscode = require('vscode'); +import { DialogResponses, IActionContext } from 'vscode-azureextensionui'; +import { DOCKERFILE_GLOB_PATTERN, FILE_SEARCH_MAX_RESULT, YAML_GLOB_PATTERN } from "../../constants"; +import { ext } from '../../extensionVariables'; + +export interface Item extends vscode.QuickPickItem { + relativeFilePath: string; + relativeFolderPath: string; +} + +async function getFileUris(folder: vscode.WorkspaceFolder, globPattern: string): Promise { + return await vscode.workspace.findFiles(new vscode.RelativePattern(folder, globPattern), undefined, FILE_SEARCH_MAX_RESULT, undefined); +} + +function createFileItem(rootFolder: vscode.WorkspaceFolder, uri: vscode.Uri): Item { + let relativeFilePath = path.join(".", uri.fsPath.substr(rootFolder.uri.fsPath.length)); + + return { + description: undefined, + relativeFilePath: relativeFilePath, + label: relativeFilePath, + relativeFolderPath: path.dirname(relativeFilePath) + }; +} + +export async function resolveFileItem(rootFolder: vscode.WorkspaceFolder, fileUri: vscode.Uri | undefined, globPattern: string, message: string): Promise { + if (fileUri) { + return createFileItem(rootFolder, fileUri); + } + + let uris: vscode.Uri[] = await getFileUris(rootFolder, globPattern); + + if (!uris || uris.length === 0) { + return undefined; + } else { + let items: Item[] = uris.map(uri => createFileItem(rootFolder, uri)); + if (items.length === 1) { + return items[0]; + } else { + const res: vscode.QuickPickItem = await ext.ui.showQuickPick(items, { placeHolder: message }); + return res; + } + } +} + +export async function quickPickDockerFileItem(actionContext: IActionContext, dockerFileUri: vscode.Uri | undefined, rootFolder: vscode.WorkspaceFolder): Promise { + let dockerFileItem: Item; + + while (!dockerFileItem) { + let resolvedItem: Item | undefined = await resolveFileItem(rootFolder, dockerFileUri, DOCKERFILE_GLOB_PATTERN, 'Choose a Dockerfile to build.'); + if (resolvedItem) { + dockerFileItem = resolvedItem; + } else { + let msg = "Couldn't find a Dockerfile in your workspace. Would you like to add Docker files to the workspace?"; + actionContext.properties.cancelStep = msg; + await ext.ui.showWarningMessage(msg, DialogResponses.yes, DialogResponses.cancel); + actionContext.properties.cancelStep = undefined; + await vscode.commands.executeCommand('vscode-docker.configure'); + // Try again + } + } + return dockerFileItem; +} + +export async function quickPickYamlFileItem(fileUri: vscode.Uri, rootFolder: vscode.WorkspaceFolder, noYamlFileMessage: string): Promise { + const fileItem: Item = await resolveFileItem(rootFolder, fileUri, YAML_GLOB_PATTERN, 'Choose a .yaml file to run.'); + if (!fileItem) { + throw new Error(noYamlFileMessage); + } + return fileItem; +} diff --git a/commands/utils/quick-pick-image.ts b/commands/utils/quick-pick-image.ts index 222a11ccf4..4614e79470 100644 --- a/commands/utils/quick-pick-image.ts +++ b/commands/utils/quick-pick-image.ts @@ -6,14 +6,13 @@ import * as Docker from 'dockerode'; import * as path from "path"; import vscode = require('vscode'); -import { DialogResponses, IActionContext, parseError, TelemetryProperties } from 'vscode-azureextensionui'; -import { DOCKERFILE_GLOB_PATTERN, YAML_GLOB_PATTERN } from '../../dockerExtension'; -import { showDockerConnectionError, throwDockerConnectionError } from '../../explorer/utils/dockerConnectionError'; +import { IActionContext, TelemetryProperties } from 'vscode-azureextensionui'; +import { throwDockerConnectionError } from '../../explorer/utils/dockerConnectionError'; import { delay } from '../../explorer/utils/utils'; import { ext } from '../../extensionVariables'; -import { Item, resolveFileItem } from '../build-image'; import { addImageTaggingTelemetry, getTagFromUserInput } from '../tag-image'; import { docker } from './docker-endpoint'; +import { Item } from './quick-pick-file'; export interface ImageItem extends vscode.QuickPickItem { label: string; @@ -112,32 +111,3 @@ export async function quickPickImageName(actionContext: IActionContext, rootFold await ext.context.globalState.update(dockerFileKey, imageName); return imageName; } - -export async function quickPickDockerFileItem(actionContext: IActionContext, dockerFileUri: vscode.Uri | undefined, rootFolder: vscode.WorkspaceFolder): Promise { - let dockerFileItem: Item; - - while (!dockerFileItem) { - let resolvedItem: Item | undefined = await resolveFileItem(rootFolder, dockerFileUri, DOCKERFILE_GLOB_PATTERN, 'Choose a Dockerfile to build.'); - if (resolvedItem) { - dockerFileItem = resolvedItem; - } else { - let msg = "Couldn't find a Dockerfile in your workspace. Would you like to add Docker files to the workspace?"; - actionContext.properties.cancelStep = msg; - await ext.ui.showWarningMessage(msg, DialogResponses.yes, DialogResponses.cancel); - actionContext.properties.cancelStep = undefined; - await vscode.commands.executeCommand('vscode-docker.configure'); - // Try again - } - } - return dockerFileItem; -} - -export async function quickPickYamlFileItem(fileUri: vscode.Uri | undefined, rootFolder: vscode.WorkspaceFolder): Promise { - let fileItem: Item; - - let resolvedItem: Item | undefined = await resolveFileItem(rootFolder, fileUri, YAML_GLOB_PATTERN, 'Choose a .yaml file to run.'); - if (resolvedItem) { - fileItem = resolvedItem; - } - return fileItem; -} diff --git a/constants.ts b/constants.ts index afa23815bc..bb9f7239da 100644 --- a/constants.ts +++ b/constants.ts @@ -34,3 +34,12 @@ export const skus = ["Standard", "Basic", "Premium"]; //Repository + Tag format export const imageTagRegExp = new RegExp('^[a-zA-Z0-9.-_/]{1,256}:(?![.-])[a-zA-Z0-9.-_]{1,128}$'); + +//GLOB Patterns +export const FROM_DIRECTIVE_PATTERN = /^\s*FROM\s*([\w-\/:]*)(\s*AS\s*[a-z][a-z0-9-_\\.]*)?$/i; +export const COMPOSE_FILE_GLOB_PATTERN = '**/[dD][oO][cC][kK][eE][rR]-[cC][oO][mM][pP][oO][sS][eE]*.{[yY][aA][mM][lL],[yY][mM][lL]}'; +export const DOCKERFILE_GLOB_PATTERN = '**/{*.[dD][oO][cC][kK][eE][rR][fF][iI][lL][eE],[dD][oO][cC][kK][eE][rR][fF][iI][lL][eE]}'; +export const YAML_GLOB_PATTERN = '**/*.{[yY][aA][mM][lL],[yY][mM][lL]}'; + +//File search max ammout +export const FILE_SEARCH_MAX_RESULT = 1000; diff --git a/dockerExtension.ts b/dockerExtension.ts index 8e66a4d0d8..c367f60ec9 100644 --- a/dockerExtension.ts +++ b/dockerExtension.ts @@ -18,7 +18,7 @@ import { createRegistry } from './commands/azureCommands/create-registry'; import { deleteAzureImage, untagAzureImage } from './commands/azureCommands/delete-image'; import { deleteAzureRegistry } from './commands/azureCommands/delete-registry'; import { deleteRepository } from './commands/azureCommands/delete-repository'; -import { pullFromAzure } from './commands/azureCommands/pull-from-azure'; +import { pullImageFromAzure, pullRepoFromAzure } from './commands/azureCommands/pull-from-azure'; import { quickBuild } from "./commands/azureCommands/quick-build"; import { runTask, runTaskFile } from "./commands/azureCommands/run-task"; import { showTaskProperties } from "./commands/azureCommands/show-task"; @@ -41,6 +41,7 @@ import { docker } from './commands/utils/docker-endpoint'; import { DefaultTerminalProvider } from './commands/utils/TerminalProvider'; import { DockerDebugConfigProvider } from './configureWorkspace/configDebugProvider'; import { configure, configureApi, ConfigureApiOptions } from './configureWorkspace/configure'; +import { COMPOSE_FILE_GLOB_PATTERN } from './constants'; import { registerDebugConfigurationProvider } from './debugging/coreclr/registerDebugger'; import { DockerComposeCompletionItemProvider } from './dockerCompose/dockerComposeCompletionItemProvider'; import { DockerComposeHoverProvider } from './dockerCompose/dockerComposeHoverProvider'; @@ -68,11 +69,6 @@ import { getTrustedCertificates } from './utils/getTrustedCertificates'; import { Keytar } from './utils/keytar'; import { wrapError } from './utils/wrapError'; -export const FROM_DIRECTIVE_PATTERN = /^\s*FROM\s*([\w-\/:]*)(\s*AS\s*[a-z][a-z0-9-_\\.]*)?$/i; -export const COMPOSE_FILE_GLOB_PATTERN = '**/[dD][oO][cC][kK][eE][rR]-[cC][oO][mM][pP][oO][sS][eE]*.{[yY][aA][mM][lL],[yY][mM][lL]}'; -export const DOCKERFILE_GLOB_PATTERN = '**/{*.[dD][oO][cC][kK][eE][rR][fF][iI][lL][eE],[dD][oO][cC][kK][eE][rR][fF][iI][lL][eE]}'; -export const YAML_GLOB_PATTERN = '**/*.{[yY][aA][mM][lL],[yY][mM][lL]}'; - export let dockerExplorerProvider: DockerExplorerProvider; export type KeyInfo = { [keyName: string]: string }; @@ -272,7 +268,8 @@ function registerDockerCommands(): void { registerCommand('vscode-docker.acr.deleteImage', deleteAzureImage); registerCommand('vscode-docker.acr.deleteRegistry', deleteAzureRegistry); registerCommand('vscode-docker.acr.deleteRepository', deleteRepository); - registerCommand('vscode-docker.acr.pullImage', pullFromAzure); + registerCommand('vscode-docker.acr.pullImage', pullImageFromAzure); + registerCommand('vscode-docker.acr.pullRepo', pullRepoFromAzure); registerCommand('vscode-docker.acr.quickBuild', async function (this: IActionContext, item: vscode.Uri | undefined): Promise { await quickBuild(this, item); }); registerCommand('vscode-docker.acr.runTask', runTask); registerCommand("vscode-docker.acr.runTaskFile", runTaskFile); diff --git a/dockerfile/dockerfileCompletionItemProvider.ts b/dockerfile/dockerfileCompletionItemProvider.ts index 5e452552fe..25e57549d0 100644 --- a/dockerfile/dockerfileCompletionItemProvider.ts +++ b/dockerfile/dockerfileCompletionItemProvider.ts @@ -6,7 +6,7 @@ 'use strict'; import { CancellationToken, CompletionItem, CompletionItemProvider, Position, TextDocument } from 'vscode'; -import { FROM_DIRECTIVE_PATTERN } from "../dockerExtension"; +import { FROM_DIRECTIVE_PATTERN } from '../constants'; import helper = require('../helpers/suggestSupportHelper'); // IntelliSense diff --git a/helpers/suggestSupportHelper.ts b/helpers/suggestSupportHelper.ts index 37ed945179..8dce1e2cde 100644 --- a/helpers/suggestSupportHelper.ts +++ b/helpers/suggestSupportHelper.ts @@ -6,7 +6,7 @@ 'use strict'; import vscode = require('vscode'); -import { FROM_DIRECTIVE_PATTERN } from "../dockerExtension"; +import { FROM_DIRECTIVE_PATTERN } from '../constants'; import hub = require('../dockerHubSearch'); import parser = require('../parser'); diff --git a/package.json b/package.json index baebd9359a..3193ec3c8a 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "onCommand:vscode-docker.acr.deleteRegistry", "onCommand:vscode-docker.acr.deleteRepository", "onCommand:vscode-docker.acr.pullImage", + "onCommand:vscode-docker.acr.pullRepo", "onCommand:vscode-docker.acr.quickBuild", "onCommand:vscode-docker.acr.runTask", "onCommand:vscode-docker.acr.runTaskFile", @@ -199,7 +200,11 @@ }, { "command": "vscode-docker.acr.pullImage", - "when": "view == dockerExplorer && viewItem =~ /^(azureImageTagNode|azureRepositoryNode)$/" + "when": "view == dockerExplorer && viewItem =~ azureImageTagNode" + }, + { + "command": "vscode-docker.acr.pullRepo", + "when": "view == dockerExplorer && viewItem =~ azureRepositoryNode" }, { "command": "vscode-docker.acr.runTask", @@ -648,7 +653,13 @@ }, { "command": "vscode-docker.acr.pullImage", - "title": "Pull Image from Azure", + "title": "Pull tag from Azure", + "category": "Docker" + }, + { + "command": "vscode-docker.acr.pullRepo", + "title": "Pull Repository from Azure", + "description": "Pull all Image tags from an Azure Repository", "category": "Docker" }, { @@ -680,7 +691,7 @@ }, { "command": "vscode-docker.acr.viewLogs", - "title": "View Azure Logs", + "title": "View Task Logs", "category": "Docker" }, {