/*--------------------------------------------------------- * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ import * as path from 'path'; import { DockerComposeHoverProvider } from './dockerCompose/dockerComposeHoverProvider'; import { DockerfileCompletionItemProvider } from './dockerfile/dockerfileCompletionItemProvider'; import { DockerComposeCompletionItemProvider } from './dockerCompose/dockerComposeCompletionItemProvider'; import composeVersionKeys from './dockerCompose/dockerComposeKeyInfo'; import { DockerComposeParser } from './dockerCompose/dockerComposeParser'; import vscode = require('vscode'); import { buildImage } from './commands/build-image'; import inspectImageCommand from './commands/inspect-image'; import { removeImage } from './commands/remove-image'; import { pushImage } from './commands/push-image'; import { startContainer, startContainerInteractive, startAzureCLI } from './commands/start-container'; import { stopContainer } from './commands/stop-container'; import { restartContainer } from './commands/restart-container'; import { showLogsContainer } from './commands/showlogs-container'; import { openShellContainer } from './commands/open-shell-container'; import { tagImage } from './commands/tag-image'; import { composeUp, composeDown } from './commands/docker-compose'; import { configure } from './configureWorkspace/configure'; import { systemPrune } from './commands/system-prune'; import { Reporter } from './telemetry/telemetry'; import DockerInspectDocumentContentProvider, { SCHEME as DOCKER_INSPECT_SCHEME } from './documentContentProviders/dockerInspect'; import { DockerExplorerProvider } from './explorer/dockerExplorer'; import { removeContainer } from './commands/remove-container'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, Middleware, Proposed, ProposedFeatures, DidChangeConfigurationNotification } from 'vscode-languageclient'; import { WebAppCreator } from './explorer/deploy/webAppCreator'; import { AzureImageNode, AzureRegistryNode, AzureRepositoryNode } from './explorer/models/azureRegistryNodes'; import { DockerHubImageNode, DockerHubRepositoryNode, DockerHubOrgNode } from './explorer/models/dockerHubNodes'; import { AzureAccountWrapper } from './explorer/deploy/azureAccountWrapper'; import * as util from "./explorer/deploy/util"; import { dockerHubLogout, browseDockerHub } from './explorer/utils/dockerHubUtils'; import { AzureAccount } from './typings/azure-account.api'; import * as opn from 'opn'; import { DockerDebugConfigProvider } from './configureWorkspace/configDebugProvider'; import { browseAzurePortal } from './explorer/utils/azureUtils'; 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]ocker-[cC]ompose*.{yaml,yml}'; export const DOCKERFILE_GLOB_PATTERN = '**/{*.dockerfile,[dD]ocker[fF]ile}'; export var diagnosticCollection: vscode.DiagnosticCollection; export var dockerExplorerProvider: DockerExplorerProvider; export type KeyInfo = { [keyName: string]: string; }; export interface ComposeVersionKeys { All: KeyInfo, v1: KeyInfo, v2: KeyInfo }; let client: LanguageClient; export async function activate(ctx: vscode.ExtensionContext): Promise { const DOCKERFILE_MODE_ID: vscode.DocumentFilter = { language: 'dockerfile', scheme: 'file' }; const installedExtensions: any[] = vscode.extensions.all; const outputChannel = util.getOutputChannel(); let azureAccount: AzureAccount; for (var i = 0; i < installedExtensions.length; i++) { const ext = installedExtensions[i]; if (ext.id === 'ms-vscode.azure-account') { try { azureAccount = await ext.activate(); } catch (error) { console.log('Failed to activate the Azure Account Extension: ' + error); } break; } } ctx.subscriptions.push(new Reporter(ctx)); dockerExplorerProvider = new DockerExplorerProvider(azureAccount); vscode.window.registerTreeDataProvider('dockerExplorer', dockerExplorerProvider); vscode.commands.registerCommand('dockerExplorer.refreshExplorer', () => dockerExplorerProvider.refresh()); vscode.commands.registerCommand('dockerExplorer.systemPrune', () => systemPrune()); ctx.subscriptions.push(vscode.languages.registerCompletionItemProvider(DOCKERFILE_MODE_ID, new DockerfileCompletionItemProvider(), '.')); const YAML_MODE_ID: vscode.DocumentFilter = { language: 'yaml', scheme: 'file', pattern: COMPOSE_FILE_GLOB_PATTERN }; var yamlHoverProvider = new DockerComposeHoverProvider(new DockerComposeParser(), composeVersionKeys.All); ctx.subscriptions.push(vscode.languages.registerHoverProvider(YAML_MODE_ID, yamlHoverProvider)); ctx.subscriptions.push(vscode.languages.registerCompletionItemProvider(YAML_MODE_ID, new DockerComposeCompletionItemProvider(), '.')); ctx.subscriptions.push(vscode.workspace.registerTextDocumentContentProvider(DOCKER_INSPECT_SCHEME, new DockerInspectDocumentContentProvider())); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.configure', configure)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.image.build', buildImage)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.image.inspect', inspectImageCommand)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.image.remove', removeImage)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.image.push', pushImage)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.image.tag', tagImage)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.container.start', startContainer)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.container.start.interactive', startContainerInteractive)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.container.start.azurecli', startAzureCLI)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.container.stop', stopContainer)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.container.restart', restartContainer)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.container.show-logs', showLogsContainer)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.container.open-shell', openShellContainer)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.container.remove', removeContainer)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.compose.up', composeUp)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.compose.down', composeDown)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.system.prune', systemPrune)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.createWebApp', async (context?: AzureImageNode | DockerHubImageNode) => { if (context) { if (azureAccount) { const azureAccountWrapper = new AzureAccountWrapper(ctx, azureAccount); const wizard = new WebAppCreator(outputChannel, azureAccountWrapper, context); const result = await wizard.run(); } else { const open: vscode.MessageItem = { title: "View in Marketplace" }; const response = await vscode.window.showErrorMessage('Please install the Azure Account extension to deploy to Azure.', open); if (response === open) { opn('https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account'); } } } })); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.dockerHubLogout', dockerHubLogout)); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.browseDockerHub', async (context?: DockerHubImageNode | DockerHubRepositoryNode | DockerHubOrgNode) => { browseDockerHub(context); })); ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.browseAzurePortal', async (context?: AzureRegistryNode | AzureRepositoryNode | AzureImageNode ) => { browseAzurePortal(context); })); ctx.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('docker', new DockerDebugConfigProvider())); activateLanguageClient(ctx); } export function deactivate(): Thenable { if (!client) { return undefined; } // perform cleanup Configuration.dispose(); return client.stop(); } namespace Configuration { let configurationListener: vscode.Disposable; export function computeConfiguration(params: Proposed.ConfigurationParams): vscode.WorkspaceConfiguration[] { if (!params.items) { return null; } let result: vscode.WorkspaceConfiguration[] = []; for (let item of params.items) { let config = null; if (item.scopeUri) { config = vscode.workspace.getConfiguration(item.section, client.protocol2CodeConverter.asUri(item.scopeUri)); } else { config = vscode.workspace.getConfiguration(item.section); } result.push(config); } return result; } export function initialize() { configurationListener = vscode.workspace.onDidChangeConfiguration(() => { // notify the language server that settings have change client.sendNotification(DidChangeConfigurationNotification.type, { settings: null }); }); } export function dispose() { if (configurationListener) { // remove this listener when disposed configurationListener.dispose(); } } } function activateLanguageClient(ctx: vscode.ExtensionContext) { let serverModule = ctx.asAbsolutePath(path.join("node_modules", "dockerfile-language-server-nodejs", "lib", "server.js")); let debugOptions = { execArgv: ["--nolazy", "--debug=6009"] }; let serverOptions: ServerOptions = { run: { module: serverModule, transport: TransportKind.ipc, args: ["--node-ipc"] }, debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } } let middleware: ProposedFeatures.ConfigurationMiddleware | Middleware = { workspace: { configuration: Configuration.computeConfiguration } }; let clientOptions: LanguageClientOptions = { documentSelector: ['dockerfile'], synchronize: { fileEvents: vscode.workspace.createFileSystemWatcher('**/.clientrc') }, middleware: middleware as Middleware } client = new LanguageClient("dockerfile-langserver", "Dockerfile Language Server", serverOptions, clientOptions); // enable the proposed workspace/configuration feature client.registerProposedFeatures(); client.onReady().then(() => { // attach the VS Code settings listener Configuration.initialize(); }); client.start(); }