Adopt VS Code's terminal profile API for cloud shell (#344)
This commit is contained in:
Родитель
0f79e272b9
Коммит
1885a843af
|
@ -61,7 +61,7 @@
|
|||
"webpack-cli": "^4.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.53.0"
|
||||
"vscode": "^1.58.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/abort-controller": {
|
||||
|
@ -8590,7 +8590,7 @@
|
|||
},
|
||||
"node_modules/safe-regex": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
|
@ -9095,6 +9095,11 @@
|
|||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
},
|
||||
"bin": {
|
||||
"sshpk-conv": "bin/sshpk-conv",
|
||||
"sshpk-sign": "bin/sshpk-sign",
|
||||
"sshpk-verify": "bin/sshpk-verify"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
@ -18313,7 +18318,7 @@
|
|||
},
|
||||
"safe-regex": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
32
package.json
32
package.json
|
@ -17,7 +17,7 @@
|
|||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"publisher": "ms-vscode",
|
||||
"engines": {
|
||||
"vscode": "^1.53.0"
|
||||
"vscode": "^1.58.0"
|
||||
},
|
||||
"categories": [
|
||||
"Azure"
|
||||
|
@ -31,10 +31,10 @@
|
|||
"onCommand:azure-account.loginToCloud",
|
||||
"onCommand:azure-account.loginWithDeviceCode",
|
||||
"onCommand:azure-account.logout",
|
||||
"onCommand:azure-account.openCloudConsoleLinux",
|
||||
"onCommand:azure-account.openCloudConsoleWindows",
|
||||
"onCommand:azure-account.selectSubscriptions",
|
||||
"onCommand:azure-account.uploadFileCloudConsole"
|
||||
"onCommand:azure-account.uploadFileCloudConsole",
|
||||
"onTerminalProfile:azure-account.cloudShellBash",
|
||||
"onTerminalProfile:azure-account.cloudShellPowerShell"
|
||||
],
|
||||
"main": "./main",
|
||||
"contributes": {
|
||||
|
@ -64,16 +64,6 @@
|
|||
"title": "%azure-account.commands.logout%",
|
||||
"category": "%azure-account.commands.azure%"
|
||||
},
|
||||
{
|
||||
"command": "azure-account.openCloudConsoleLinux",
|
||||
"title": "%azure-account.commands.openCloudConsoleLinux%",
|
||||
"category": "%azure-account.commands.azure%"
|
||||
},
|
||||
{
|
||||
"command": "azure-account.openCloudConsoleWindows",
|
||||
"title": "%azure-account.commands.openCloudConsoleWindows%",
|
||||
"category": "%azure-account.commands.azure%"
|
||||
},
|
||||
{
|
||||
"command": "azure-account.selectSubscriptions",
|
||||
"title": "%azure-account.commands.selectSubscriptions%",
|
||||
|
@ -101,6 +91,20 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"terminal": {
|
||||
"profiles": [
|
||||
{
|
||||
"title": "%azure-account.cloudShellBash%",
|
||||
"id": "azure-account.cloudShellBash",
|
||||
"icon": "azure"
|
||||
},
|
||||
{
|
||||
"title": "%azure-account.cloudShellPowerShell%",
|
||||
"id": "azure-account.cloudShellPowerShell",
|
||||
"icon": "azure"
|
||||
}
|
||||
]
|
||||
},
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"title": "Azure configuration",
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"azure-account.cloudShellBash": "Azure Cloud Shell (Bash)",
|
||||
"azure-account.cloudShellPowerShell": "Azure Cloud Shell (PowerShell)",
|
||||
"azure-account.commands.azure": "Azure",
|
||||
"azure-account.commands.createAccount": "Create an Account",
|
||||
"azure-account.commands.login": "Sign In",
|
||||
"azure-account.commands.loginToCloud": "Sign In to Azure Cloud",
|
||||
"azure-account.commands.loginWithDeviceCode": "Sign In with Device Code",
|
||||
"azure-account.commands.logout": "Sign Out",
|
||||
"azure-account.commands.openCloudConsoleLinux": "Open Bash in Cloud Shell",
|
||||
"azure-account.commands.openCloudConsoleWindows": "Open PowerShell in Cloud Shell",
|
||||
"azure-account.commands.selectSubscriptions": "Select Subscriptions",
|
||||
"azure-account.commands.uploadFileCloudConsole": "Upload to Cloud Shell"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Terminal, TerminalProfile } from "vscode";
|
||||
import { CloudShell, CloudShellStatus } from "../azure-account.api";
|
||||
|
||||
export interface CloudShellInternal extends Omit<CloudShell, 'terminal'> {
|
||||
status: CloudShellStatus;
|
||||
terminal?: Promise<Terminal>;
|
||||
terminalProfile?: Promise<TerminalProfile>;
|
||||
}
|
|
@ -14,7 +14,7 @@ import * as path from 'path';
|
|||
import * as semver from 'semver';
|
||||
import { parse, UrlWithStringQuery } from 'url';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { commands, Disposable, env, EventEmitter, MessageItem, QuickPickItem, Terminal, Uri, window } from 'vscode';
|
||||
import { CancellationToken, commands, Disposable, env, EventEmitter, MessageItem, QuickPickItem, Terminal, TerminalOptions, TerminalProfile, ThemeIcon, Uri, window } from 'vscode';
|
||||
import { AzureAccountExtensionApi, AzureLoginStatus, AzureSession, CloudShell, CloudShellStatus, UploadOptions } from '../azure-account.api';
|
||||
import { AzureSession as AzureSessionLegacy } from '../azure-account.legacy.api';
|
||||
import { ext } from '../extensionVariables';
|
||||
|
@ -23,10 +23,9 @@ import { TelemetryReporter } from '../telemetry';
|
|||
import { localize } from '../utils/localize';
|
||||
import { Deferred } from '../utils/promiseUtils';
|
||||
import { AccessTokens, connectTerminal, ConsoleUris, Errors, getUserSettings, provisionConsole, resetConsole, Size, UserSettings } from './cloudConsoleLauncher';
|
||||
import { CloudShellInternal } from './CloudShellInternal';
|
||||
import { createServer, Queue, readJSON, Server } from './ipc';
|
||||
|
||||
|
||||
|
||||
interface OS {
|
||||
id: 'linux' | 'windows';
|
||||
shellName: string;
|
||||
|
@ -37,10 +36,6 @@ export type OSName = 'Linux' | 'Windows';
|
|||
|
||||
type OSes = { Linux: OS, Windows: OS };
|
||||
|
||||
interface CloudShellWritable extends CloudShell {
|
||||
status: CloudShellStatus
|
||||
}
|
||||
|
||||
export const OSes: OSes = {
|
||||
Linux: {
|
||||
id: 'linux',
|
||||
|
@ -170,13 +165,14 @@ function getUploadFile(tokens: Promise<AccessTokens>, uris: Promise<ConsoleUris>
|
|||
}
|
||||
}
|
||||
|
||||
export const shells: CloudShell[] = [];
|
||||
export function createCloudConsole(api: AzureAccountExtensionApi, reporter: TelemetryReporter, osName: OSName): CloudShell {
|
||||
export const shells: CloudShellInternal[] = [];
|
||||
export function createCloudConsole(api: AzureAccountExtensionApi, reporter: TelemetryReporter, osName: OSName, terminalProfileToken?: CancellationToken): CloudShellInternal {
|
||||
const os: OS = OSes[osName];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let liveServerQueue: Queue<any> | undefined;
|
||||
const event: EventEmitter<CloudShellStatus> = new EventEmitter<CloudShellStatus>();
|
||||
let deferredTerminal: Deferred<Terminal>;
|
||||
let deferredTerminalProfile: Deferred<TerminalProfile>;
|
||||
let deferredSession: Deferred<AzureSession>;
|
||||
let deferredTokens: Deferred<AccessTokens>;
|
||||
const tokensPromise: Promise<AccessTokens> = new Promise<AccessTokens>((resolve, reject) => deferredTokens = { resolve, reject });
|
||||
|
@ -184,17 +180,18 @@ export function createCloudConsole(api: AzureAccountExtensionApi, reporter: Tele
|
|||
const urisPromise: Promise<ConsoleUris> = new Promise<ConsoleUris>((resolve, reject) => deferredUris = { resolve, reject });
|
||||
let deferredInitialSize: Deferred<Size>;
|
||||
const initialSizePromise: Promise<Size> = new Promise<Size>((resolve, reject) => deferredInitialSize = { resolve, reject });
|
||||
const state: CloudShellWritable = {
|
||||
const state: CloudShellInternal = {
|
||||
status: 'Connecting',
|
||||
onStatusChanged: event.event,
|
||||
waitForConnection,
|
||||
terminal: new Promise<Terminal>((resolve, reject) => deferredTerminal = { resolve, reject }),
|
||||
terminalProfile: new Promise<TerminalProfile>((resolve, reject) => deferredTerminalProfile = { resolve, reject }),
|
||||
session: new Promise<AzureSession>((resolve, reject) => deferredSession = { resolve, reject }),
|
||||
uploadFile: getUploadFile(tokensPromise, urisPromise)
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
state.terminal.catch(() => { }); // ignore
|
||||
state.terminal?.catch(() => { }); // ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
state.session.catch(() => { }); // ignore
|
||||
shells.push(state);
|
||||
|
@ -204,6 +201,7 @@ export function createCloudConsole(api: AzureAccountExtensionApi, reporter: Tele
|
|||
event.fire(state.status);
|
||||
if (status === 'Disconnected') {
|
||||
deferredTerminal.reject(status);
|
||||
deferredTerminalProfile.reject(status);
|
||||
deferredSession.reject(status);
|
||||
deferredTokens.reject(status);
|
||||
deferredUris.reject(status);
|
||||
|
@ -266,14 +264,14 @@ export function createCloudConsole(api: AzureAccountExtensionApi, reporter: Tele
|
|||
|
||||
// open terminal
|
||||
let shellPath: string = path.join(ext.context.asAbsolutePath('bin'), `node.${isWindows ? 'bat' : 'sh'}`);
|
||||
let modulePath: string = path.join(ext.context.asAbsolutePath('dist'), 'cloudConsoleLauncher');
|
||||
let cloudConsoleLauncherPath: string = path.join(ext.context.asAbsolutePath('dist'), 'cloudConsoleLauncher');
|
||||
if (isWindows) {
|
||||
modulePath = modulePath.replace(/\\/g, '\\\\');
|
||||
cloudConsoleLauncherPath = cloudConsoleLauncherPath.replace(/\\/g, '\\\\');
|
||||
}
|
||||
const shellArgs: string[] = [
|
||||
process.argv0,
|
||||
'-e',
|
||||
`require('${modulePath}').main()`,
|
||||
`require('${cloudConsoleLauncherPath}').main()`,
|
||||
];
|
||||
|
||||
if (isWindows) {
|
||||
|
@ -282,25 +280,47 @@ export function createCloudConsole(api: AzureAccountExtensionApi, reporter: Tele
|
|||
shellArgs.shift();
|
||||
}
|
||||
|
||||
const terminal: Terminal = window.createTerminal({
|
||||
name: localize('azure-account.cloudConsole', "{0} in Cloud Shell", os.shellName),
|
||||
const terminalOptions: TerminalOptions = {
|
||||
name: localize('azureCloudShell', 'Azure Cloud Shell ({0})', os.shellName),
|
||||
iconPath: new ThemeIcon('azure'),
|
||||
shellPath,
|
||||
shellArgs,
|
||||
env: {
|
||||
CLOUD_CONSOLE_IPC: server.ipcHandlePath,
|
||||
}
|
||||
});
|
||||
const subscription: Disposable = window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
liveServerQueue = undefined;
|
||||
subscription.dispose();
|
||||
server.dispose();
|
||||
updateStatus('Disconnected');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const cleanupCloudShell = () => {
|
||||
liveServerQueue = undefined;
|
||||
server.dispose();
|
||||
updateStatus('Disconnected');
|
||||
}
|
||||
|
||||
// Open the appropriate type of VS Code terminal depending on the entry point
|
||||
if (terminalProfileToken) {
|
||||
// Entry point: Terminal profile provider
|
||||
const terminalProfileCloseSubscription = terminalProfileToken.onCancellationRequested(() => {
|
||||
terminalProfileCloseSubscription.dispose();
|
||||
cleanupCloudShell();
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
deferredTerminalProfile!.resolve(new TerminalProfile(terminalOptions));
|
||||
} else {
|
||||
// Entry point: Extension API
|
||||
const terminal: Terminal = window.createTerminal(terminalOptions);
|
||||
const terminalCloseSubscription = window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
terminalCloseSubscription.dispose();
|
||||
cleanupCloudShell();
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
deferredTerminal!.resolve(terminal);
|
||||
}
|
||||
|
||||
liveServerQueue = serverQueue;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
deferredTerminal!.resolve(terminal);
|
||||
|
||||
const loginStatus: AzureLoginStatus = await waitForLoginStatus(api);
|
||||
if (loginStatus !== 'LoggedIn') {
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
import { createReadStream } from 'fs';
|
||||
import { basename } from 'path';
|
||||
import { commands, ConfigurationTarget, env, ExtensionContext, ProgressLocation, Uri, window, workspace, WorkspaceConfiguration } from 'vscode';
|
||||
import { CancellationToken, commands, ConfigurationTarget, env, ExtensionContext, ProgressLocation, Uri, window, workspace, WorkspaceConfiguration } from 'vscode';
|
||||
import { createApiProvider, createAzExtOutputChannel, createExperimentationService, registerUIExtensionVariables } from 'vscode-azureextensionui';
|
||||
import { AzureExtensionApiProvider } from 'vscode-azureextensionui/api';
|
||||
import { AzureAccountExtensionApi } from './azure-account.api';
|
||||
import { OSes, OSName, shells } from './cloudConsole/cloudConsole';
|
||||
import { createCloudConsole, OSes, OSName, shells } from './cloudConsole/cloudConsole';
|
||||
import { cloudSetting, displayName, extensionPrefix, showSignedInEmailSetting } from './constants';
|
||||
import { ext } from './extensionVariables';
|
||||
import { AzureLoginHelper } from './login/AzureLoginHelper';
|
||||
|
@ -41,9 +41,19 @@ export async function activateInternal(context: ExtensionContext, perfStats: { l
|
|||
}
|
||||
context.subscriptions.push(createStatusBarItem(context, azureLoginHelper.api));
|
||||
context.subscriptions.push(commands.registerCommand('azure-account.createAccount', createAccount));
|
||||
context.subscriptions.push(commands.registerCommand('azure-account.openCloudConsoleLinux', () => cloudConsole(azureLoginHelper.api, 'Linux')));
|
||||
context.subscriptions.push(commands.registerCommand('azure-account.openCloudConsoleWindows', () => cloudConsole(azureLoginHelper.api, 'Windows')));
|
||||
context.subscriptions.push(commands.registerCommand('azure-account.uploadFileCloudConsole', uri => uploadFile(azureLoginHelper.api, uri)));
|
||||
|
||||
window.registerTerminalProfileProvider('azure-account.cloudShellBash', {
|
||||
provideTerminalProfile: (token: CancellationToken) => {
|
||||
return createCloudConsole(azureLoginHelper.api, reporter, 'Linux', token).terminalProfile;
|
||||
}
|
||||
});
|
||||
window.registerTerminalProfileProvider('azure-account.cloudShellPowerShell', {
|
||||
provideTerminalProfile: (token: CancellationToken) => {
|
||||
return createCloudConsole(azureLoginHelper.api, reporter, 'Windows', token).terminalProfile;
|
||||
}
|
||||
});
|
||||
|
||||
survey(context, reporter);
|
||||
|
||||
reporter.sendSanitizedEvent('activate', { 'activationTime': String((perfStats.loadEndTime - perfStats.loadStartTime) / 1000) });
|
||||
|
|
|
@ -71,8 +71,7 @@ export class AzureAccountExtensionApi implements types.AzureAccountExtensionApi
|
|||
}
|
||||
|
||||
public createCloudShell(os: OSName): types.CloudShell {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return createCloudConsole(this, this.azureLoginHelper.reporter, os)!;
|
||||
return <types.CloudShell>createCloudConsole(this, this.azureLoginHelper.reporter, os);
|
||||
}
|
||||
|
||||
private sendIsLegacyApiTelemetry(eventName: string, isLegacyApi?: boolean): void {
|
||||
|
|
Загрузка…
Ссылка в новой задаче