mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add extension api for calling azdata commands (#11763)
* Add extension api for calling azdata commands * Update typings file name
This commit is contained in:
@@ -9,15 +9,34 @@ import { HttpClient } from './common/httpClient';
|
|||||||
import * as loc from './localizedConstants';
|
import * as loc from './localizedConstants';
|
||||||
import { executeCommand, executeSudoCommand } from './common/childProcess';
|
import { executeCommand, executeSudoCommand } from './common/childProcess';
|
||||||
import { searchForCmd } from './common/utils';
|
import { searchForCmd } from './common/utils';
|
||||||
|
import { AzdataOutput } from './typings/azdata-ext';
|
||||||
|
|
||||||
export const azdataHostname = 'https://aka.ms';
|
export const azdataHostname = 'https://aka.ms';
|
||||||
export const azdataUri = 'azdata-msi';
|
export const azdataUri = 'azdata-msi';
|
||||||
/**
|
|
||||||
* Information about an azdata installation
|
export interface IAzdataTool {
|
||||||
*/
|
|
||||||
export interface IAzdata {
|
|
||||||
path: string,
|
path: string,
|
||||||
version: string
|
version: string,
|
||||||
|
/**
|
||||||
|
* Executes azdata with the specified arguments (e.g. --version) and returns the result
|
||||||
|
* @param args The args to pass to azdata
|
||||||
|
* @param parseResult A function used to parse out the raw result into the desired shape
|
||||||
|
*/
|
||||||
|
executeCommand<R>(args: string[], parseResult: (result: any) => R[]): Promise<AzdataOutput<R>>
|
||||||
|
}
|
||||||
|
|
||||||
|
class AzdataTool implements IAzdataTool {
|
||||||
|
constructor(public path: string, public version: string, private _outputChannel: vscode.OutputChannel) { }
|
||||||
|
|
||||||
|
public async executeCommand<R>(args: string[], parseResult: (result: any) => R[]): Promise<AzdataOutput<R>> {
|
||||||
|
const output = JSON.parse((await executeCommand(`"${this.path}"`, args.concat(['--output', 'json']), this._outputChannel)).stdout);
|
||||||
|
return {
|
||||||
|
logs: <string[]>output.log,
|
||||||
|
stdout: <string[]>output.stdout,
|
||||||
|
stderr: <string[]>output.stderr,
|
||||||
|
result: parseResult(output.result)
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,10 +44,10 @@ export interface IAzdata {
|
|||||||
* or encountered an unexpected error.
|
* or encountered an unexpected error.
|
||||||
* @param outputChannel Channel used to display diagnostic information
|
* @param outputChannel Channel used to display diagnostic information
|
||||||
*/
|
*/
|
||||||
export async function findAzdata(outputChannel: vscode.OutputChannel): Promise<IAzdata> {
|
export async function findAzdata(outputChannel: vscode.OutputChannel): Promise<IAzdataTool> {
|
||||||
outputChannel.appendLine(loc.searchingForAzdata);
|
outputChannel.appendLine(loc.searchingForAzdata);
|
||||||
try {
|
try {
|
||||||
let azdata: IAzdata | undefined = undefined;
|
let azdata: IAzdataTool | undefined = undefined;
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
azdata = await findAzdataWin32(outputChannel);
|
azdata = await findAzdataWin32(outputChannel);
|
||||||
@@ -112,7 +131,7 @@ async function installAzdataLinux(outputChannel: vscode.OutputChannel): Promise<
|
|||||||
* Finds azdata specifically on Windows
|
* Finds azdata specifically on Windows
|
||||||
* @param outputChannel Channel used to display diagnostic information
|
* @param outputChannel Channel used to display diagnostic information
|
||||||
*/
|
*/
|
||||||
async function findAzdataWin32(outputChannel: vscode.OutputChannel): Promise<IAzdata> {
|
async function findAzdataWin32(outputChannel: vscode.OutputChannel): Promise<IAzdataTool> {
|
||||||
const promise = searchForCmd('azdata.cmd');
|
const promise = searchForCmd('azdata.cmd');
|
||||||
return findSpecificAzdata(await promise, outputChannel);
|
return findSpecificAzdata(await promise, outputChannel);
|
||||||
}
|
}
|
||||||
@@ -122,12 +141,9 @@ async function findAzdataWin32(outputChannel: vscode.OutputChannel): Promise<IAz
|
|||||||
* @param path The path to the azdata executable
|
* @param path The path to the azdata executable
|
||||||
* @param outputChannel Channel used to display diagnostic information
|
* @param outputChannel Channel used to display diagnostic information
|
||||||
*/
|
*/
|
||||||
async function findSpecificAzdata(path: string, outputChannel: vscode.OutputChannel): Promise<IAzdata> {
|
async function findSpecificAzdata(path: string, outputChannel: vscode.OutputChannel): Promise<IAzdataTool> {
|
||||||
const versionOutput = await executeCommand(path, ['--version'], outputChannel);
|
const versionOutput = await executeCommand(path, ['--version'], outputChannel);
|
||||||
return {
|
return new AzdataTool(path, parseVersion(versionOutput.stdout), outputChannel);
|
||||||
path: path,
|
|
||||||
version: parseVersion(versionOutput.stdout)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
39
extensions/azdata/src/common/azdataUtils.ts
Normal file
39
extensions/azdata/src/common/azdataUtils.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { PostgresServerListResult, SqlInstanceListResult } from '../typings/azdata-ext';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to parse the raw output from the `azdata postgres server list` command
|
||||||
|
* @param result The raw JSON result array
|
||||||
|
*/
|
||||||
|
export function parsePostgresServerListResult(result: any[]): PostgresServerListResult[] {
|
||||||
|
return result.map(r => {
|
||||||
|
return {
|
||||||
|
id: r['ID'],
|
||||||
|
clusterIP: r['clusterIP'],
|
||||||
|
externalIP: r['externalIP'],
|
||||||
|
mustRestart: r['mustRestart'],
|
||||||
|
name: r['name'],
|
||||||
|
status: r['status']
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to parse the raw output from the `azdata sql instance list` command
|
||||||
|
* @param result The raw JSON result array
|
||||||
|
*/
|
||||||
|
export function parseSqlInstanceListResult(result: any[]): SqlInstanceListResult[] {
|
||||||
|
return result.map(r => {
|
||||||
|
return {
|
||||||
|
clusterEndpoint: r['Cluster Endpoint'],
|
||||||
|
externalEndpoint: r['External Endpoint'],
|
||||||
|
name: r['Name'],
|
||||||
|
status: r['Status'],
|
||||||
|
vCores: r['VCores']
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -3,22 +3,49 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as azdata from './typings/azdata-ext';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { findAzdata } from './azdata';
|
import { findAzdata, IAzdataTool } from './azdata';
|
||||||
|
import { parsePostgresServerListResult, parseSqlInstanceListResult } from './common/azdataUtils';
|
||||||
|
|
||||||
export async function activate(): Promise<void> {
|
let localAzdata: IAzdataTool | undefined = undefined;
|
||||||
|
|
||||||
|
export async function activate(): Promise<azdata.IExtension> {
|
||||||
const outputChannel = vscode.window.createOutputChannel('azdata');
|
const outputChannel = vscode.window.createOutputChannel('azdata');
|
||||||
await checkForAzdata(outputChannel);
|
localAzdata = await checkForAzdata(outputChannel);
|
||||||
|
return {
|
||||||
|
postgres: {
|
||||||
|
server: {
|
||||||
|
list: async () => {
|
||||||
|
if (!localAzdata) {
|
||||||
|
throw new Error('No azdata');
|
||||||
|
}
|
||||||
|
return localAzdata.executeCommand(['postgres', 'server', 'list'], parsePostgresServerListResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sql: {
|
||||||
|
instance: {
|
||||||
|
list: async () => {
|
||||||
|
if (!localAzdata) {
|
||||||
|
throw new Error('No azdata');
|
||||||
|
}
|
||||||
|
return localAzdata.executeCommand(['sql', 'instance', 'list'], parseSqlInstanceListResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkForAzdata(outputChannel: vscode.OutputChannel): Promise<void> {
|
async function checkForAzdata(outputChannel: vscode.OutputChannel): Promise<IAzdataTool | undefined> {
|
||||||
try {
|
try {
|
||||||
await findAzdata(outputChannel);
|
return await findAzdata(outputChannel);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Don't block on this since we want the extension to finish activating without needing user input.
|
// Don't block on this since we want the extension to finish activating without needing user input.
|
||||||
// Calls will be made to handle azdata not being installed
|
// Calls will be made to handle azdata not being installed
|
||||||
promptToInstallAzdata(outputChannel).catch(e => console.log(`Unexpected error prompting to install azdata ${e}`));
|
promptToInstallAzdata(outputChannel).catch(e => console.log(`Unexpected error prompting to install azdata ${e}`));
|
||||||
}
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function promptToInstallAzdata(_outputChannel: vscode.OutputChannel): Promise<void> {
|
async function promptToInstallAzdata(_outputChannel: vscode.OutputChannel): Promise<void> {
|
||||||
|
|||||||
51
extensions/azdata/src/typings/azdata-ext.d.ts
vendored
Normal file
51
extensions/azdata/src/typings/azdata-ext.d.ts
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Covers defining what the azdata extension exports to other extensions
|
||||||
|
*
|
||||||
|
* IMPORTANT: THIS IS NOT A HARD DEFINITION unlike vscode; therefore no enums or classes should be defined here
|
||||||
|
* (const enums get evaluated when typescript -> javascript so those are fine)
|
||||||
|
*/
|
||||||
|
export const enum extension {
|
||||||
|
name = 'Microsoft.azdata'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SqlInstanceListResult {
|
||||||
|
clusterEndpoint: string,
|
||||||
|
externalEndpoint: string,
|
||||||
|
name: string,
|
||||||
|
status: string,
|
||||||
|
vCores: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PostgresServerListResult {
|
||||||
|
id: string,
|
||||||
|
clusterIP: string,
|
||||||
|
externalIP: string,
|
||||||
|
mustRestart: boolean,
|
||||||
|
name: string,
|
||||||
|
status: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AzdataOutput<R> {
|
||||||
|
logs: string[],
|
||||||
|
result: R[],
|
||||||
|
stderr: string[],
|
||||||
|
stdout: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IExtension {
|
||||||
|
postgres: {
|
||||||
|
server: {
|
||||||
|
list(): Promise<AzdataOutput<PostgresServerListResult>>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sql: {
|
||||||
|
instance: {
|
||||||
|
list(): Promise<AzdataOutput<SqlInstanceListResult>>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user