mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Remove REST API from Arc extension (#11888)
* wip * Remove old API * Fix tests
This commit is contained in:
@@ -7,7 +7,7 @@ import * as os from 'os';
|
||||
import * as vscode from 'vscode';
|
||||
import { HttpClient } from './common/httpClient';
|
||||
import * as loc from './localizedConstants';
|
||||
import { executeCommand, executeSudoCommand } from './common/childProcess';
|
||||
import { executeCommand, executeSudoCommand, ExitCodeError } from './common/childProcess';
|
||||
import { searchForCmd } from './common/utils';
|
||||
import { AzdataOutput } from './typings/azdata-ext';
|
||||
|
||||
@@ -22,20 +22,30 @@ export interface IAzdataTool {
|
||||
* @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>>
|
||||
executeCommand<R>(args: string[], additionalEnvVars?: { [key: string]: string }): 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)
|
||||
};
|
||||
public async executeCommand<R>(args: string[], additionalEnvVars?: { [key: string]: string }): Promise<AzdataOutput<R>> {
|
||||
try {
|
||||
const output = JSON.parse((await executeCommand(`"${this.path}"`, args.concat(['--output', 'json']), this._outputChannel, additionalEnvVars)).stdout);
|
||||
return {
|
||||
logs: <string[]>output.log,
|
||||
stdout: <string[]>output.stdout,
|
||||
stderr: <string[]>output.stderr,
|
||||
result: <R>output.result
|
||||
};
|
||||
} catch (err) {
|
||||
// Since the output is JSON we need to do some extra parsing here to get the correct stderr out.
|
||||
// The actual value we get is something like ERROR: { stderr: '...' } so we also need to trim
|
||||
// off the start that isn't a valid JSON blob
|
||||
if (err instanceof ExitCodeError) {
|
||||
err.stderr = JSON.parse(err.stderr.substring(err.stderr.indexOf('{'))).stderr;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +152,7 @@ async function findAzdataWin32(outputChannel: vscode.OutputChannel): Promise<IAz
|
||||
* @param outputChannel Channel used to display diagnostic information
|
||||
*/
|
||||
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 new AzdataTool(path, parseVersion(versionOutput.stdout), outputChannel);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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']
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -12,8 +12,30 @@ import * as loc from '../localizedConstants';
|
||||
* Wrapper error for when an unexpected exit code was received
|
||||
*/
|
||||
export class ExitCodeError extends Error {
|
||||
constructor(public code: number) {
|
||||
super(loc.unexpectedExitCode(code));
|
||||
constructor(private _code: number, private _stderr: string) {
|
||||
super();
|
||||
this.setMessage();
|
||||
}
|
||||
|
||||
public get code(): number {
|
||||
return this._code;
|
||||
}
|
||||
|
||||
public set code(value: number) {
|
||||
this._code = value;
|
||||
}
|
||||
|
||||
public get stderr(): string {
|
||||
return this._stderr;
|
||||
}
|
||||
|
||||
public set stderr(value: string) {
|
||||
this._stderr = value;
|
||||
this.setMessage();
|
||||
}
|
||||
|
||||
private setMessage(): void {
|
||||
this.message = loc.unexpectedExitCode(this._code, this._stderr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +45,16 @@ export type ProcessOutput = { stdout: string, stderr: string };
|
||||
* Executes the specified command. Throws an error for a non-0 exit code or if stderr receives output
|
||||
* @param command The command to execute
|
||||
* @param args Optional args to pass, every arg and arg value must be a separate item in the array
|
||||
* @param additionalEnvVars Additional environment variables to add to the process environment
|
||||
* @param outputChannel Channel used to display diagnostic information
|
||||
*/
|
||||
export async function executeCommand(command: string, args: string[], outputChannel: vscode.OutputChannel): Promise<ProcessOutput> {
|
||||
export async function executeCommand(command: string, args: string[], outputChannel: vscode.OutputChannel, additionalEnvVars?: { [key: string]: string },): Promise<ProcessOutput> {
|
||||
return new Promise((resolve, reject) => {
|
||||
outputChannel.appendLine(loc.executingCommand(command, args));
|
||||
const stdoutBuffers: Buffer[] = [];
|
||||
const stderrBuffers: Buffer[] = [];
|
||||
const child = cp.spawn(command, args, { shell: true });
|
||||
const env = Object.assign({}, process.env, additionalEnvVars);
|
||||
const child = cp.spawn(command, args, { shell: true, env: env });
|
||||
child.stdout.on('data', (b: Buffer) => stdoutBuffers.push(b));
|
||||
child.stderr.on('data', (b: Buffer) => stderrBuffers.push(b));
|
||||
child.on('error', reject);
|
||||
@@ -44,7 +68,7 @@ export async function executeCommand(command: string, args: string[], outputChan
|
||||
outputChannel.appendLine(loc.stdoutOutput(stderr));
|
||||
}
|
||||
if (code) {
|
||||
const err = new ExitCodeError(code);
|
||||
const err = new ExitCodeError(code, stderr);
|
||||
outputChannel.appendLine(err.message);
|
||||
reject(err);
|
||||
} else {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import * as azdata from './typings/azdata-ext';
|
||||
import * as vscode from 'vscode';
|
||||
import { findAzdata, IAzdataTool } from './azdata';
|
||||
import { parsePostgresServerListResult, parseSqlInstanceListResult } from './common/azdataUtils';
|
||||
|
||||
let localAzdata: IAzdataTool | undefined = undefined;
|
||||
|
||||
@@ -14,29 +13,51 @@ export async function activate(): Promise<azdata.IExtension> {
|
||||
const outputChannel = vscode.window.createOutputChannel('azdata');
|
||||
localAzdata = await checkForAzdata(outputChannel);
|
||||
return {
|
||||
dc: {
|
||||
endpoint: {
|
||||
list: async () => {
|
||||
return executeLocalAzdataCommand(['arc', 'dc', 'endpoint', 'list']);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
show: async () => {
|
||||
return executeLocalAzdataCommand(['arc', 'dc', 'config', 'show']);
|
||||
}
|
||||
}
|
||||
},
|
||||
login: async (endpoint: string, username: string, password: string) => {
|
||||
return executeLocalAzdataCommand(['login', '-e', endpoint, '-u', username], { 'AZDATA_PASSWORD': password });
|
||||
},
|
||||
postgres: {
|
||||
server: {
|
||||
list: async () => {
|
||||
if (!localAzdata) {
|
||||
throw new Error('No azdata');
|
||||
}
|
||||
return localAzdata.executeCommand(['postgres', 'server', 'list'], parsePostgresServerListResult);
|
||||
return executeLocalAzdataCommand(['arc', 'postgres', 'server', 'list']);
|
||||
},
|
||||
show: async (name: string) => {
|
||||
return executeLocalAzdataCommand(['arc', 'postgres', 'server', 'show', '-n', name]);
|
||||
}
|
||||
}
|
||||
},
|
||||
sql: {
|
||||
instance: {
|
||||
mi: {
|
||||
list: async () => {
|
||||
if (!localAzdata) {
|
||||
throw new Error('No azdata');
|
||||
}
|
||||
return localAzdata.executeCommand(['sql', 'instance', 'list'], parseSqlInstanceListResult);
|
||||
return executeLocalAzdataCommand(['arc', 'sql', 'mi', 'list']);
|
||||
},
|
||||
show: async (name: string) => {
|
||||
return executeLocalAzdataCommand(['arc', 'sql', 'mi', 'show', '-n', name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function executeLocalAzdataCommand<R>(args: string[], additionalEnvVars?: { [key: string]: string }): Promise<azdata.AzdataOutput<R>> {
|
||||
if (!localAzdata) {
|
||||
throw new Error('No azdata');
|
||||
}
|
||||
return localAzdata.executeCommand(args, additionalEnvVars);
|
||||
}
|
||||
|
||||
async function checkForAzdata(outputChannel: vscode.OutputChannel): Promise<IAzdataTool | undefined> {
|
||||
try {
|
||||
return await findAzdata(outputChannel);
|
||||
|
||||
@@ -27,4 +27,4 @@ export const downloadError = localize('azdata.downloadError', "Error while downl
|
||||
export function installError(err: any): string { return localize('azdata.installError', "Error installing azdata : {0}", err.message ?? err); }
|
||||
export function platformUnsupported(platform: string): string { return localize('azdata.platformUnsupported', "Platform '{0}' is currently unsupported", platform); }
|
||||
export function unexpectedCommandError(errMsg: string): string { return localize('azdata.unexpectedCommandError', "Unexpected error executing command : {0}", errMsg); }
|
||||
export function unexpectedExitCode(code: number): string { return localize('azdata.unexpectedExitCode', "Unexpected exit code from command : {0}", code); }
|
||||
export function unexpectedExitCode(code: number, err: string): string { return localize('azdata.unexpectedExitCode', "Unexpected exit code from command : {1} ({0})", code, err); }
|
||||
|
||||
202
extensions/azdata/src/typings/azdata-ext.d.ts
vendored
202
extensions/azdata/src/typings/azdata-ext.d.ts
vendored
@@ -13,39 +13,211 @@ export const enum extension {
|
||||
name = 'Microsoft.azdata'
|
||||
}
|
||||
|
||||
export interface SqlInstanceListResult {
|
||||
clusterEndpoint: string,
|
||||
externalEndpoint: string,
|
||||
export interface DcEndpointListResult {
|
||||
description: string,
|
||||
endpoint: string,
|
||||
name: string,
|
||||
status: string,
|
||||
vCores: string
|
||||
protocol: string
|
||||
}
|
||||
|
||||
export interface SqlMiListResult {
|
||||
name: string,
|
||||
replicas: string,
|
||||
serverEndpoint: string,
|
||||
state: string
|
||||
}
|
||||
|
||||
export interface PostgresServerListResult {
|
||||
id: string,
|
||||
clusterIP: string,
|
||||
externalIP: string,
|
||||
mustRestart: boolean,
|
||||
name: string,
|
||||
status: string
|
||||
state: string,
|
||||
workers: number
|
||||
}
|
||||
|
||||
export interface DcConfigShowResult {
|
||||
apiVersion: string,
|
||||
kind: string,
|
||||
metadata: {
|
||||
creationTimestamp: string,
|
||||
generation: number,
|
||||
name: string,
|
||||
namespace: string,
|
||||
resourceVersion: string,
|
||||
selfLink: string,
|
||||
uid: string
|
||||
},
|
||||
spec: {
|
||||
credentials: {
|
||||
controllerAdmin: string,
|
||||
dockerRegistry: string,
|
||||
serviceAccount: string
|
||||
},
|
||||
docker: {
|
||||
imagePullPolicy: string,
|
||||
imageTag: string,
|
||||
registry: string,
|
||||
repository: string
|
||||
},
|
||||
security: {
|
||||
allowDumps: string,
|
||||
allowNodeMetricsCollection: boolean,
|
||||
allowPodMetricsCollection: boolean,
|
||||
allowRunAsRoot: false
|
||||
},
|
||||
services: [
|
||||
{
|
||||
name: string,
|
||||
port: number,
|
||||
serviceType: string
|
||||
},
|
||||
{
|
||||
name: string,
|
||||
port: number,
|
||||
serviceType: string
|
||||
}
|
||||
],
|
||||
settings: {
|
||||
ElasticSearch: {
|
||||
'vm.max_map_count': string
|
||||
},
|
||||
controller: {
|
||||
enableBilling: string,
|
||||
'logs.rotation.days': string,
|
||||
'logs.rotation.size': string
|
||||
}
|
||||
},
|
||||
storage: {
|
||||
data: {
|
||||
accessMode: string,
|
||||
className: string,
|
||||
size: string
|
||||
},
|
||||
logs: {
|
||||
accessMode: string,
|
||||
className: string,
|
||||
size: string
|
||||
}
|
||||
}
|
||||
},
|
||||
status: {
|
||||
state: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface SqlMiShowResult {
|
||||
apiVersion: string, // "sql.arcdata.microsoft.com/v1alpha1"
|
||||
kind: string, // "sqlmanagedinstance"
|
||||
metadata: {
|
||||
creationTimestamp: string, // "2020-08-19T17:35:45Z"
|
||||
generation: number, // 1
|
||||
name: string, // "miaa-instance"
|
||||
namespace: string, // "arc"
|
||||
resourceVersion: string, // "202623"
|
||||
selfLink: string, // "/apis/sql.arcdata.microsoft.com/v1alpha1/namespaces/arc/sqlmanagedinstances/miaa-instance"
|
||||
uid: string // "cea737aa-3f82-4f6a-9bed-2b51c2c33dff"
|
||||
},
|
||||
spec: {
|
||||
storage: {
|
||||
data: {
|
||||
className: string, // "local-storage"
|
||||
size: string // "5Gi"
|
||||
},
|
||||
logs: {
|
||||
className: string, // "local-storage"
|
||||
size: string // "5Gi"
|
||||
}
|
||||
}
|
||||
},
|
||||
status: {
|
||||
readyReplicas: string, // "1/1"
|
||||
state: string // "Ready"
|
||||
}
|
||||
}
|
||||
|
||||
export interface PostgresServerShowResult {
|
||||
apiVersion: string, // "arcdata.microsoft.com/v1alpha1"
|
||||
kind: string, // "postgresql-12"
|
||||
metadata: {
|
||||
creationTimestamp: string, // "2020-08-19T20:25:11Z"
|
||||
generation: number, // 1
|
||||
name: string, // "chgagnon-pg"
|
||||
namespace: string, // "arc",
|
||||
resourceVersion: string, // "214944",
|
||||
selfLink: string, // "/apis/arcdata.microsoft.com/v1alpha1/namespaces/arc/postgresql-12s/chgagnon-pg",
|
||||
uid: string, // "26d0f5bb-0c0b-4225-a6b5-5be2bf6feac0"
|
||||
},
|
||||
spec: {
|
||||
backups: {
|
||||
deltaMinutes: number, // 3,
|
||||
fullMinutes: number, // 10,
|
||||
tiers: [
|
||||
{
|
||||
retention: {
|
||||
maximums: string[], // [ "6", "512MB" ],
|
||||
minimums: string[], // [ "3" ]
|
||||
},
|
||||
storage: {
|
||||
volumeSize: string, // "1Gi"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
scale: {
|
||||
shards: number // 1
|
||||
},
|
||||
scheduling: {
|
||||
default: {
|
||||
resources: {
|
||||
requests: {
|
||||
memory: string, // "256Mi"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
storage: {
|
||||
data: {
|
||||
className: string, // "local-storage",
|
||||
size: string // "5Gi"
|
||||
},
|
||||
logs: {
|
||||
className: string, // "local-storage",
|
||||
size: string // "5Gi"
|
||||
}
|
||||
}
|
||||
},
|
||||
status: {
|
||||
readyPods: string, // "1/1",
|
||||
state: string // "Ready"
|
||||
}
|
||||
}
|
||||
|
||||
export interface AzdataOutput<R> {
|
||||
logs: string[],
|
||||
result: R[],
|
||||
result: R,
|
||||
stderr: string[],
|
||||
stdout: string[]
|
||||
stdout: string[],
|
||||
code?: number
|
||||
}
|
||||
|
||||
export interface IExtension {
|
||||
dc: {
|
||||
endpoint: {
|
||||
list(): Promise<AzdataOutput<DcEndpointListResult[]>>
|
||||
},
|
||||
config: {
|
||||
show(): Promise<AzdataOutput<DcConfigShowResult>>
|
||||
}
|
||||
},
|
||||
login(endpoint: string, username: string, password: string): Promise<AzdataOutput<any>>,
|
||||
postgres: {
|
||||
server: {
|
||||
list(): Promise<AzdataOutput<PostgresServerListResult>>
|
||||
list(): Promise<AzdataOutput<PostgresServerListResult[]>>,
|
||||
show(name: string): Promise<AzdataOutput<PostgresServerShowResult>>
|
||||
}
|
||||
},
|
||||
sql: {
|
||||
instance: {
|
||||
list(): Promise<AzdataOutput<SqlInstanceListResult>>
|
||||
mi: {
|
||||
list(): Promise<AzdataOutput<SqlMiListResult[]>>,
|
||||
show(name: string): Promise<AzdataOutput<SqlMiShowResult>>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user