mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-13 11:38:36 -05:00
Change azdata executions to point to kube config and cluster contexts (#13569)
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
"display_name": "Python 3",
|
||||
"language": "python"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
"display_name": "Python 3",
|
||||
"language": "python"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
|
||||
@@ -663,6 +663,8 @@
|
||||
"variableNames": {
|
||||
"endpoint": "AZDATA_NB_VAR_CONTROLLER_ENDPOINT",
|
||||
"username": "AZDATA_NB_VAR_CONTROLLER_USERNAME",
|
||||
"kubeConfig": "AZDATA_NB_VAR_CONTROLLER_KUBECONFIG",
|
||||
"clusterContext": "AZDATA_NB_VAR_CONTROLLER_KUBECTL_CONTEXT",
|
||||
"password": "AZDATA_NB_VAR_CONTROLLER_PASSWORD"
|
||||
}
|
||||
},
|
||||
@@ -855,6 +857,8 @@
|
||||
"variableNames": {
|
||||
"endpoint": "AZDATA_NB_VAR_CONTROLLER_ENDPOINT",
|
||||
"username": "AZDATA_NB_VAR_CONTROLLER_USERNAME",
|
||||
"kubeConfig": "AZDATA_NB_VAR_CONTROLLER_KUBECONFIG",
|
||||
"clusterContext": "AZDATA_NB_VAR_CONTROLLER_KUBECTL_CONTEXT",
|
||||
"password": "AZDATA_NB_VAR_CONTROLLER_PASSWORD"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -28,14 +28,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<arc.IE
|
||||
});
|
||||
|
||||
vscode.commands.registerCommand('arc.connectToController', async () => {
|
||||
const nodes = await treeDataProvider.getChildren();
|
||||
if (nodes.length > 0) {
|
||||
const response = await vscode.window.showErrorMessage(loc.onlyOneControllerSupported, loc.yes, loc.no);
|
||||
if (response !== loc.yes) {
|
||||
return;
|
||||
}
|
||||
await treeDataProvider.removeController(nodes[0] as ControllerTreeNode);
|
||||
}
|
||||
const dialog = new ConnectToControllerDialog(treeDataProvider);
|
||||
dialog.showDialog();
|
||||
const model = await dialog.waitForClose();
|
||||
|
||||
@@ -196,9 +196,8 @@ export function couldNotFindAzureResource(name: string): string { return localiz
|
||||
export function passwordResetFailed(error: any): string { return localize('arc.passwordResetFailed', "Failed to reset password. {0}", getErrorMessage(error)); }
|
||||
export function errorConnectingToController(error: any): string { return localize('arc.errorConnectingToController', "Error connecting to controller. {0}", getErrorMessage(error, true)); }
|
||||
export function passwordAcquisitionFailed(error: any): string { return localize('arc.passwordAcquisitionFailed', "Failed to acquire password. {0}", getErrorMessage(error)); }
|
||||
export const invalidPassword = localize('arc.invalidPassword', "The password did not work, try again.");
|
||||
export const loginFailed = localize('arc.loginFailed', "Error logging into controller, try again.");
|
||||
export function errorVerifyingPassword(error: any): string { return localize('arc.errorVerifyingPassword', "Error encountered while verifying password. {0}", getErrorMessage(error)); }
|
||||
export const onlyOneControllerSupported = localize('arc.onlyOneControllerSupported', "Only one controller connection is currently supported at this time. Do you wish to remove the existing connection and add a new one?");
|
||||
export const noControllersConnected = localize('noControllersConnected', "No Azure Arc controllers are currently connected. Please run the command: 'Connect to Existing Azure Arc Controller' and then try again");
|
||||
export const variableValueFetchForUnsupportedVariable = (variableName: string) => localize('getVariableValue.unknownVariableName', "Attempt to get variable value for unknown variable:{0}", variableName);
|
||||
export const isPasswordFetchForUnsupportedVariable = (variableName: string) => localize('getIsPassword.unknownVariableName', "Attempt to get isPassword for unknown variable:{0}", variableName);
|
||||
@@ -211,4 +210,5 @@ export const select = localize('button.label', "Select");
|
||||
export const noContextFound = (configFile: string) => localize('noContextFound', "No 'contexts' found in the config file: {0}", configFile);
|
||||
export const noCurrentContextFound = (configFile: string) => localize('noCurrentContextFound', "No context is marked as 'current-context' in the config file: {0}", configFile);
|
||||
export const noNameInContext = (configFile: string) => localize('noNameInContext', "No name field was found in a cluster context in the config file: {0}", configFile);
|
||||
export const userCancelledError = localize('userCancelledError', "User cancelled the dialog");
|
||||
export const userCancelledError = localize('arc.userCancelledError', "User cancelled the dialog");
|
||||
export const clusterContextConfigNoLongerValid = (configFile: string, clusterContext: string, error: any) => localize('clusterContextConfigNoLongerValid', "The cluster context information specified by config file: {0} and cluster context: {1} is no longer valid. Error is:\n\t{2}\n Do you want to update this information?", configFile, clusterContext, getErrorMessage(error));
|
||||
|
||||
@@ -7,6 +7,8 @@ import { ControllerInfo, ResourceType } from 'arc';
|
||||
import * as azdataExt from 'azdata-ext';
|
||||
import * as vscode from 'vscode';
|
||||
import { UserCancelledError } from '../common/api';
|
||||
import { getCurrentClusterContext, getKubeConfigClusterContexts } from '../common/kubeUtils';
|
||||
import { Deferred } from '../common/promise';
|
||||
import * as loc from '../localizedConstants';
|
||||
import { ConnectToControllerDialog } from '../ui/dialogs/connectControllerDialog';
|
||||
import { AzureArcTreeDataProvider } from '../ui/tree/azureArcTreeDataProvider';
|
||||
@@ -22,6 +24,7 @@ export class ControllerModel {
|
||||
private _endpoints: azdataExt.DcEndpointListResult[] = [];
|
||||
private _registrations: Registration[] = [];
|
||||
private _controllerConfig: azdataExt.DcConfigShowResult | undefined = undefined;
|
||||
private static _refreshInProgress: Deferred<void> | undefined = undefined;
|
||||
|
||||
private readonly _onConfigUpdated = new vscode.EventEmitter<azdataExt.DcConfigShowResult | undefined>();
|
||||
private readonly _onEndpointsUpdated = new vscode.EventEmitter<azdataExt.DcEndpointListResult[]>();
|
||||
@@ -50,19 +53,41 @@ export class ControllerModel {
|
||||
this._onInfoUpdated.fire(this._info);
|
||||
}
|
||||
|
||||
public get azdataAdditionalEnvVars(): azdataExt.AdditionalEnvVars {
|
||||
return {
|
||||
'KUBECONFIG': this.info.kubeConfigFilePath,
|
||||
'KUBECTL_CONTEXT': this.info.kubeClusterContext
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls azdata login to set the context to this controller
|
||||
* @param promptReconnect
|
||||
*/
|
||||
public async azdataLogin(promptReconnect: boolean = false): Promise<void> {
|
||||
// We haven't gotten our password yet or we want to prompt for a reconnect
|
||||
if (!this._password || promptReconnect) {
|
||||
let promptForValidClusterContext: boolean = false;
|
||||
try {
|
||||
const contexts = await getKubeConfigClusterContexts(this.info.kubeConfigFilePath);
|
||||
getCurrentClusterContext(contexts, this.info.kubeClusterContext, true); // this throws if this.info.kubeClusterContext is not found in 'contexts'
|
||||
} catch (error) {
|
||||
const response = await vscode.window.showErrorMessage(loc.clusterContextConfigNoLongerValid(this.info.kubeConfigFilePath, this.info.kubeClusterContext, error), loc.yes, loc.no);
|
||||
if (response === loc.yes) {
|
||||
promptForValidClusterContext = true;
|
||||
} else {
|
||||
if (!promptReconnect) { //throw unless we are required to prompt for reconnect anyways
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We haven't gotten our password yet or we want to prompt for a reconnect or we want to prompt to reacquire valid cluster context or any and all of these.
|
||||
if (!this._password || promptReconnect || promptForValidClusterContext) {
|
||||
this._password = '';
|
||||
if (this.info.rememberPassword) {
|
||||
// It should be in the credentials store, get it from there
|
||||
this._password = await this.treeDataProvider.getPassword(this.info);
|
||||
}
|
||||
if (promptReconnect || !this._password) {
|
||||
if (promptReconnect || !this._password || promptForValidClusterContext) {
|
||||
// No password yet or we want to re-prompt for credentials so prompt for it from the user
|
||||
const dialog = new ConnectToControllerDialog(this.treeDataProvider);
|
||||
dialog.showDialog(this.info, this._password);
|
||||
@@ -70,13 +95,14 @@ export class ControllerModel {
|
||||
if (model) {
|
||||
await this.treeDataProvider.addOrUpdateController(model.controllerModel, model.password, false);
|
||||
this._password = model.password;
|
||||
this._info = model.controllerModel.info;
|
||||
} else {
|
||||
throw new UserCancelledError(loc.userCancelledError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this._azdataApi.azdata.login(this.info.url, this.info.username, this._password);
|
||||
await this._azdataApi.azdata.login(this.info.url, this.info.username, this._password, this.azdataAdditionalEnvVars);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,6 +117,12 @@ export class ControllerModel {
|
||||
}
|
||||
}
|
||||
public async refresh(showErrors: boolean = true, promptReconnect: boolean = false): Promise<void> {
|
||||
//wait for any previous refresh that might be in progress to finish
|
||||
if (ControllerModel._refreshInProgress) {
|
||||
await ControllerModel._refreshInProgress;
|
||||
}
|
||||
// create a new in progress promise object
|
||||
ControllerModel._refreshInProgress = new Deferred<void>();
|
||||
await this.azdataLogin(promptReconnect);
|
||||
const newRegistrations: Registration[] = [];
|
||||
await Promise.all([
|
||||
@@ -108,7 +140,7 @@ export class ControllerModel {
|
||||
this._onConfigUpdated.fire(this._controllerConfig);
|
||||
throw err;
|
||||
}),
|
||||
this._azdataApi.azdata.arc.dc.endpoint.list().then(result => {
|
||||
this._azdataApi.azdata.arc.dc.endpoint.list(this.azdataAdditionalEnvVars).then(result => {
|
||||
this._endpoints = result.result;
|
||||
this.endpointsLastUpdated = new Date();
|
||||
this._onEndpointsUpdated.fire(this._endpoints);
|
||||
@@ -123,7 +155,7 @@ export class ControllerModel {
|
||||
throw err;
|
||||
}),
|
||||
Promise.all([
|
||||
this._azdataApi.azdata.arc.postgres.server.list().then(result => {
|
||||
this._azdataApi.azdata.arc.postgres.server.list(this.azdataAdditionalEnvVars).then(result => {
|
||||
newRegistrations.push(...result.result.map(r => {
|
||||
return {
|
||||
instanceName: r.name,
|
||||
@@ -147,6 +179,8 @@ export class ControllerModel {
|
||||
this._onRegistrationsUpdated.fire(this._registrations);
|
||||
})
|
||||
]);
|
||||
ControllerModel._refreshInProgress.resolve();
|
||||
ControllerModel._refreshInProgress = undefined;
|
||||
}
|
||||
|
||||
public get endpoints(): azdataExt.DcEndpointListResult[] {
|
||||
|
||||
@@ -38,8 +38,8 @@ export class MiaaModel extends ResourceModel {
|
||||
|
||||
private _refreshPromise: Deferred<void> | undefined = undefined;
|
||||
|
||||
constructor(private _controllerModel: ControllerModel, private _miaaInfo: MiaaResourceInfo, registration: Registration, private _treeDataProvider: AzureArcTreeDataProvider) {
|
||||
super(_miaaInfo, registration);
|
||||
constructor(controllerModel: ControllerModel, private _miaaInfo: MiaaResourceInfo, registration: Registration, private _treeDataProvider: AzureArcTreeDataProvider) {
|
||||
super(controllerModel, _miaaInfo, registration);
|
||||
this._azdataApi = <azdataExt.IExtension>vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export class MiaaModel extends ResourceModel {
|
||||
}
|
||||
this._refreshPromise = new Deferred();
|
||||
try {
|
||||
await this._controllerModel.azdataLogin();
|
||||
await this.controllerModel.azdataLogin();
|
||||
try {
|
||||
const result = await this._azdataApi.azdata.arc.sql.mi.show(this.info.name);
|
||||
this._config = result.result;
|
||||
@@ -180,7 +180,7 @@ export class MiaaModel extends ResourceModel {
|
||||
if (this.info.connectionId) {
|
||||
try {
|
||||
const credentialProvider = await azdata.credentials.getProvider(credentialNamespace);
|
||||
const credentials = await credentialProvider.readCredential(createCredentialId(this._controllerModel.info.id, this.info.resourceType, this.info.name));
|
||||
const credentials = await credentialProvider.readCredential(createCredentialId(this.controllerModel.info.id, this.info.resourceType, this.info.name));
|
||||
if (credentials.password) {
|
||||
// Try to connect to verify credentials are still valid
|
||||
connectionProfile.password = credentials.password;
|
||||
@@ -189,7 +189,7 @@ export class MiaaModel extends ResourceModel {
|
||||
const result = await azdata.connection.connect(connectionProfile, false, false);
|
||||
if (!result.connected) {
|
||||
vscode.window.showErrorMessage(loc.connectToSqlFailed(connectionProfile.serverName, result.errorMessage));
|
||||
const connectToSqlDialog = new ConnectToSqlDialog(this._controllerModel, this);
|
||||
const connectToSqlDialog = new ConnectToSqlDialog(this.controllerModel, this);
|
||||
connectToSqlDialog.showDialog(connectionProfile);
|
||||
connectionProfile = await connectToSqlDialog.waitForClose();
|
||||
}
|
||||
@@ -203,7 +203,7 @@ export class MiaaModel extends ResourceModel {
|
||||
|
||||
if (!connectionProfile?.userName || !connectionProfile?.password) {
|
||||
// Need to prompt user for password since we don't have one stored
|
||||
const connectToSqlDialog = new ConnectToSqlDialog(this._controllerModel, this);
|
||||
const connectToSqlDialog = new ConnectToSqlDialog(this.controllerModel, this);
|
||||
connectToSqlDialog.showDialog(connectionProfile);
|
||||
connectionProfile = await connectToSqlDialog.waitForClose();
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ export class PostgresModel extends ResourceModel {
|
||||
|
||||
private _refreshPromise?: Deferred<void>;
|
||||
|
||||
constructor(private _controllerModel: ControllerModel, info: ResourceInfo, registration: Registration) {
|
||||
super(info, registration);
|
||||
constructor(controllerModel: ControllerModel, info: ResourceInfo, registration: Registration) {
|
||||
super(controllerModel, info, registration);
|
||||
this._azdataApi = <azdataExt.IExtension>vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ export class PostgresModel extends ResourceModel {
|
||||
this._refreshPromise = new Deferred();
|
||||
|
||||
try {
|
||||
await this._controllerModel.azdataLogin();
|
||||
await this.controllerModel.azdataLogin();
|
||||
this._config = (await this._azdataApi.azdata.arc.postgres.server.show(this.info.name)).result;
|
||||
this.configLastUpdated = new Date();
|
||||
this._onConfigUpdated.fire(this._config);
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
|
||||
import { ResourceInfo } from 'arc';
|
||||
import * as vscode from 'vscode';
|
||||
import { Registration } from './controllerModel';
|
||||
import { ControllerModel, Registration } from './controllerModel';
|
||||
|
||||
export abstract class ResourceModel {
|
||||
|
||||
private readonly _onRegistrationUpdated = new vscode.EventEmitter<Registration>();
|
||||
public onRegistrationUpdated = this._onRegistrationUpdated.event;
|
||||
|
||||
constructor(public info: ResourceInfo, private _registration: Registration) { }
|
||||
constructor(public readonly controllerModel: ControllerModel, public info: ResourceInfo, private _registration: Registration) { }
|
||||
|
||||
public get registration(): Registration {
|
||||
return this._registration;
|
||||
|
||||
@@ -35,6 +35,8 @@ export class ArcControllersOptionsSourceProvider implements rd.IOptionsSourcePro
|
||||
switch (variableName) {
|
||||
case 'endpoint': return controller.info.url;
|
||||
case 'username': return controller.info.username;
|
||||
case 'kubeConfig': return controller.info.kubeConfigFilePath;
|
||||
case 'clusterContext': return controller.info.kubeClusterContext;
|
||||
case 'password': return this.getPassword(controller);
|
||||
default: throw new Error(loc.variableValueFetchForUnsupportedVariable(variableName));
|
||||
}
|
||||
@@ -59,6 +61,8 @@ export class ArcControllersOptionsSourceProvider implements rd.IOptionsSourcePro
|
||||
switch (variableName) {
|
||||
case 'endpoint': return false;
|
||||
case 'username': return false;
|
||||
case 'kubeConfig': return false;
|
||||
case 'clusterContext': return false;
|
||||
case 'password': return true;
|
||||
default: throw new Error(loc.isPasswordFetchForUnsupportedVariable(variableName));
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ export class FakeAzdataApi implements azdataExt.IAzdataApi {
|
||||
workers?: number
|
||||
},
|
||||
_engineVersion?: string,
|
||||
_additionalEnvVars?: { [key: string]: string }): Promise<azdataExt.AzdataOutput<void>> { throw new Error('Method not implemented.'); }
|
||||
_additionalEnvVars?: azdataExt.AdditionalEnvVars
|
||||
): Promise<azdataExt.AzdataOutput<void>> { throw new Error('Method not implemented.'); }
|
||||
}
|
||||
},
|
||||
sql: {
|
||||
|
||||
@@ -12,6 +12,7 @@ import * as TypeMoq from 'typemoq';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import * as vscode from 'vscode';
|
||||
import * as loc from '../../localizedConstants';
|
||||
import * as kubeUtils from '../../common/kubeUtils';
|
||||
import { UserCancelledError } from '../../common/api';
|
||||
import { ControllerModel } from '../../models/controllerModel';
|
||||
import { ConnectToControllerDialog } from '../../ui/dialogs/connectControllerDialog';
|
||||
@@ -34,6 +35,8 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
beforeEach(function (): void {
|
||||
sinon.stub(ConnectToControllerDialog.prototype, 'showDialog');
|
||||
sinon.stub(kubeUtils, 'getKubeConfigClusterContexts').resolves([{ name: 'currentCluster', isCurrentContext: true }]);
|
||||
sinon.stub(vscode.window, 'showErrorMessage').resolves(<any>loc.yes);
|
||||
});
|
||||
|
||||
it('Rejected with expected error when user cancels', async function (): Promise<void> {
|
||||
@@ -61,7 +64,7 @@ describe('ControllerModel', function (): void {
|
||||
const model = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), { id: uuid(), url: '127.0.0.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', username: 'admin', name: 'arc', rememberPassword: true, resources: [] });
|
||||
|
||||
await model.azdataLogin();
|
||||
azdataMock.verify(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password), TypeMoq.Times.once());
|
||||
azdataMock.verify(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password, TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
});
|
||||
|
||||
it('Prompt for password when not in cred store', async function (): Promise<void> {
|
||||
@@ -87,7 +90,7 @@ describe('ControllerModel', function (): void {
|
||||
const model = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), { id: uuid(), url: '127.0.0.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', username: 'admin', name: 'arc', rememberPassword: true, resources: [] });
|
||||
|
||||
await model.azdataLogin();
|
||||
azdataMock.verify(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password), TypeMoq.Times.once());
|
||||
azdataMock.verify(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password, TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
});
|
||||
|
||||
it('Prompt for password when rememberPassword is true but prompt reconnect is true', async function (): Promise<void> {
|
||||
@@ -113,7 +116,7 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
await model.azdataLogin(true);
|
||||
should(waitForCloseStub.called).be.true('waitForClose should have been called');
|
||||
azdataMock.verify(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password), TypeMoq.Times.once());
|
||||
azdataMock.verify(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password, TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
});
|
||||
|
||||
it('Prompt for password when we already have a password but prompt reconnect is true', async function (): Promise<void> {
|
||||
@@ -140,7 +143,7 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
await model.azdataLogin(true);
|
||||
should(waitForCloseStub.called).be.true('waitForClose should have been called');
|
||||
azdataMock.verify(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password), TypeMoq.Times.once());
|
||||
azdataMock.verify(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password, TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
});
|
||||
|
||||
it('Model values are updated correctly when modified during reconnect', async function (): Promise<void> {
|
||||
|
||||
@@ -11,6 +11,7 @@ import * as sinon from 'sinon';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import * as vscode from 'vscode';
|
||||
import * as azdataExt from 'azdata-ext';
|
||||
import * as kubeUtils from '../../../common/kubeUtils';
|
||||
import { ControllerModel } from '../../../models/controllerModel';
|
||||
import { MiaaModel } from '../../../models/miaaModel';
|
||||
import { AzureArcTreeDataProvider } from '../../../ui/tree/azureArcTreeDataProvider';
|
||||
@@ -102,13 +103,14 @@ describe('AzureArcTreeDataProvider tests', function (): void {
|
||||
mockArcApi.setup(x => x.azdata).returns(() => fakeAzdataApi);
|
||||
|
||||
sinon.stub(vscode.extensions, 'getExtension').returns(mockArcExtension.object);
|
||||
sinon.stub(kubeUtils, 'getKubeConfigClusterContexts').resolves([{ name: 'currentCluster', isCurrentContext: true }]);
|
||||
const controllerModel = new ControllerModel(treeDataProvider, { id: uuid(), url: '127.0.0.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', username: 'sa', rememberPassword: true, resources: [] }, 'mypassword');
|
||||
await treeDataProvider.addOrUpdateController(controllerModel, '');
|
||||
const controllerNode = treeDataProvider.getControllerNode(controllerModel);
|
||||
const children = await treeDataProvider.getChildren(controllerNode);
|
||||
should(children.filter(c => c.label === fakeAzdataApi.postgresInstances[0].name).length).equal(1, 'Should have a Postgres child');
|
||||
should(children.filter(c => c.label === fakeAzdataApi.miaaInstances[0].name).length).equal(1, 'Should have a MIAA child');
|
||||
should(children.length).equal(2, 'Should have excatly 2 children');
|
||||
should(children.length).equal(2, 'Should have exactly 2 children');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export class FilePicker implements IReadOnly {
|
||||
});
|
||||
|
||||
if (!fileUris || fileUris.length === 0) {
|
||||
return; // This can happen when a user cancels out. we don't throw and the user just won't be able to move on until they select something.
|
||||
return; // This can happen when a user cancels out. We don't throw and the user just won't be able to move on until they select something.
|
||||
}
|
||||
const fileUri = fileUris[0]; //we allow the user to select only one file in the dialog
|
||||
this.filePathInputBox.value = fileUri.fsPath;
|
||||
|
||||
@@ -130,6 +130,7 @@ export class MiaaComputeAndStoragePage extends DashboardPage {
|
||||
},
|
||||
async (_progress, _token): Promise<void> => {
|
||||
try {
|
||||
await this._miaaModel.controllerModel.azdataLogin();
|
||||
await this._azdataApi.azdata.arc.sql.mi.edit(
|
||||
this._miaaModel.info.name, this.saveArgs);
|
||||
} catch (err) {
|
||||
|
||||
@@ -205,8 +205,9 @@ export class MiaaDashboardOverviewPage extends DashboardPage {
|
||||
title: loc.deletingInstance(this._miaaModel.info.name),
|
||||
cancellable: false
|
||||
},
|
||||
(_progress, _token) => {
|
||||
return this._azdataApi.azdata.arc.sql.mi.delete(this._miaaModel.info.name);
|
||||
async (_progress, _token) => {
|
||||
await this._controllerModel.azdataLogin();
|
||||
return await this._azdataApi.azdata.arc.sql.mi.delete(this._miaaModel.info.name);
|
||||
}
|
||||
);
|
||||
await this._controllerModel.refreshTreeNode();
|
||||
|
||||
@@ -156,10 +156,12 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
|
||||
},
|
||||
async (_progress, _token): Promise<void> => {
|
||||
try {
|
||||
await this._postgresModel.controllerModel.azdataLogin();
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
this.saveArgs,
|
||||
this._postgresModel.engineVersion);
|
||||
this._postgresModel.engineVersion
|
||||
);
|
||||
} catch (err) {
|
||||
// If an error occurs while editing the instance then re-enable the save button since
|
||||
// the edit wasn't successfully applied
|
||||
|
||||
@@ -151,6 +151,7 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
try {
|
||||
const password = await promptAndConfirmPassword(input => !input ? loc.enterANonEmptyPassword : '');
|
||||
if (password) {
|
||||
await this._postgresModel.controllerModel.azdataLogin();
|
||||
await this._azdataApi.azdata.arc.postgres.server.edit(
|
||||
this._postgresModel.info.name,
|
||||
{
|
||||
@@ -158,7 +159,8 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
noWait: true
|
||||
},
|
||||
this._postgresModel.engineVersion,
|
||||
{ 'AZDATA_PASSWORD': password });
|
||||
{ 'AZDATA_PASSWORD': password }
|
||||
);
|
||||
vscode.window.showInformationMessage(loc.passwordReset);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -185,8 +187,9 @@ export class PostgresOverviewPage extends DashboardPage {
|
||||
title: loc.deletingInstance(this._postgresModel.info.name),
|
||||
cancellable: false
|
||||
},
|
||||
(_progress, _token) => {
|
||||
return this._azdataApi.azdata.arc.postgres.server.delete(this._postgresModel.info.name);
|
||||
async (_progress, _token) => {
|
||||
await this._postgresModel.controllerModel.azdataLogin();
|
||||
return await this._azdataApi.azdata.arc.postgres.server.delete(this._postgresModel.info.name);
|
||||
}
|
||||
);
|
||||
await this._controllerModel.refreshTreeNode();
|
||||
|
||||
@@ -271,11 +271,19 @@ export class PasswordToControllerDialog extends ControllerDialogBase {
|
||||
}
|
||||
const azdataApi = <azdataExt.IExtension>vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
|
||||
try {
|
||||
await azdataApi.azdata.login(this.urlInputBox.value!, this.usernameInputBox.value!, this.passwordInputBox.value);
|
||||
await azdataApi.azdata.login(
|
||||
this.urlInputBox.value!,
|
||||
this.usernameInputBox.value!,
|
||||
this.passwordInputBox.value,
|
||||
{
|
||||
'KUBECONFIG': this.kubeConfigInputBox.value!,
|
||||
'KUBECTL_CONTEXT': this.clusterContextRadioGroup.value!
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
if (getErrorMessage(e).match(/Wrong username or password/i)) {
|
||||
this.dialog.message = {
|
||||
text: loc.invalidPassword,
|
||||
text: loc.loginFailed,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
};
|
||||
return false;
|
||||
@@ -299,3 +307,5 @@ export class PasswordToControllerDialog extends ControllerDialogBase {
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,47 +45,47 @@ export function getAzdataApi(localAzdataDiscovered: Promise<IAzdataTool | undefi
|
||||
return {
|
||||
arc: {
|
||||
dc: {
|
||||
create: async (namespace: string, name: string, connectivityMode: string, resourceGroup: string, location: string, subscription: string, profileName?: string, storageClass?: string) => {
|
||||
create: async (namespace: string, name: string, connectivityMode: string, resourceGroup: string, location: string, subscription: string, profileName?: string, storageClass?: string, additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.dc.create(namespace, name, connectivityMode, resourceGroup, location, subscription, profileName, storageClass);
|
||||
return azdataToolService.localAzdata.arc.dc.create(namespace, name, connectivityMode, resourceGroup, location, subscription, profileName, storageClass, additionalEnvVars);
|
||||
},
|
||||
endpoint: {
|
||||
list: async () => {
|
||||
list: async (additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.dc.endpoint.list();
|
||||
return azdataToolService.localAzdata.arc.dc.endpoint.list(additionalEnvVars);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
list: async () => {
|
||||
list: async (additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.dc.config.list();
|
||||
return azdataToolService.localAzdata.arc.dc.config.list(additionalEnvVars);
|
||||
},
|
||||
show: async () => {
|
||||
show: async (additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.dc.config.show();
|
||||
return azdataToolService.localAzdata.arc.dc.config.show(additionalEnvVars);
|
||||
}
|
||||
}
|
||||
},
|
||||
postgres: {
|
||||
server: {
|
||||
delete: async (name: string) => {
|
||||
delete: async (name: string, additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.postgres.server.delete(name);
|
||||
return azdataToolService.localAzdata.arc.postgres.server.delete(name, additionalEnvVars);
|
||||
},
|
||||
list: async () => {
|
||||
list: async (additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.postgres.server.list();
|
||||
return azdataToolService.localAzdata.arc.postgres.server.list(additionalEnvVars);
|
||||
},
|
||||
show: async (name: string) => {
|
||||
show: async (name: string, additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.postgres.server.show(name);
|
||||
return azdataToolService.localAzdata.arc.postgres.server.show(name, additionalEnvVars);
|
||||
},
|
||||
edit: async (
|
||||
name: string,
|
||||
@@ -112,20 +112,20 @@ export function getAzdataApi(localAzdataDiscovered: Promise<IAzdataTool | undefi
|
||||
},
|
||||
sql: {
|
||||
mi: {
|
||||
delete: async (name: string) => {
|
||||
delete: async (name: string, additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.sql.mi.delete(name);
|
||||
return azdataToolService.localAzdata.arc.sql.mi.delete(name, additionalEnvVars);
|
||||
},
|
||||
list: async () => {
|
||||
list: async (additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.sql.mi.list();
|
||||
return azdataToolService.localAzdata.arc.sql.mi.list(additionalEnvVars);
|
||||
},
|
||||
show: async (name: string) => {
|
||||
show: async (name: string, additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.sql.mi.show(name);
|
||||
return azdataToolService.localAzdata.arc.sql.mi.show(name, additionalEnvVars);
|
||||
},
|
||||
edit: async (
|
||||
name: string,
|
||||
@@ -135,10 +135,12 @@ export function getAzdataApi(localAzdataDiscovered: Promise<IAzdataTool | undefi
|
||||
memoryLimit?: string;
|
||||
memoryRequest?: string;
|
||||
noWait?: boolean;
|
||||
}) => {
|
||||
},
|
||||
additionalEnvVars?: azdataExt.AdditionalEnvVars
|
||||
) => {
|
||||
await localAzdataDiscovered;
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.arc.sql.mi.edit(name, args);
|
||||
return azdataToolService.localAzdata.arc.sql.mi.edit(name, args, additionalEnvVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,9 +150,9 @@ export function getAzdataApi(localAzdataDiscovered: Promise<IAzdataTool | undefi
|
||||
throwIfNoAzdata(azdataToolService.localAzdata);
|
||||
return azdataToolService.localAzdata.getPath();
|
||||
},
|
||||
login: async (endpoint: string, username: string, password: string) => {
|
||||
login: async (endpoint: string, username: string, password: string, additionalEnvVars?: azdataExt.AdditionalEnvVars) => {
|
||||
throwIfNoAzdataOrEulaNotAccepted(azdataToolService.localAzdata, isEulaAccepted(memento));
|
||||
return azdataToolService.localAzdata.login(endpoint, username, password);
|
||||
return azdataToolService.localAzdata.login(endpoint, username, password, additionalEnvVars);
|
||||
},
|
||||
getSemVersion: async () => {
|
||||
await localAzdataDiscovered;
|
||||
|
||||
@@ -31,7 +31,7 @@ export interface IAzdataTool extends azdataExt.IAzdataApi {
|
||||
* @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[], additionalEnvVars?: { [key: string]: string }): Promise<azdataExt.AzdataOutput<R>>
|
||||
executeCommand<R>(args: string[], additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<R>>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +62,7 @@ export class AzdataTool implements azdataExt.IAzdataApi {
|
||||
|
||||
public arc = {
|
||||
dc: {
|
||||
create: (namespace: string, name: string, connectivityMode: string, resourceGroup: string, location: string, subscription: string, profileName?: string, storageClass?: string): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
create: (namespace: string, name: string, connectivityMode: string, resourceGroup: string, location: string, subscription: string, profileName?: string, storageClass?: string, additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
const args = ['arc', 'dc', 'create',
|
||||
'--namespace', namespace,
|
||||
'--name', name,
|
||||
@@ -76,32 +76,32 @@ export class AzdataTool implements azdataExt.IAzdataApi {
|
||||
if (storageClass) {
|
||||
args.push('--storage-class', storageClass);
|
||||
}
|
||||
return this.executeCommand<void>(args);
|
||||
return this.executeCommand<void>(args, additionalEnvVars);
|
||||
},
|
||||
endpoint: {
|
||||
list: (): Promise<azdataExt.AzdataOutput<azdataExt.DcEndpointListResult[]>> => {
|
||||
return this.executeCommand<azdataExt.DcEndpointListResult[]>(['arc', 'dc', 'endpoint', 'list']);
|
||||
list: (additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<azdataExt.DcEndpointListResult[]>> => {
|
||||
return this.executeCommand<azdataExt.DcEndpointListResult[]>(['arc', 'dc', 'endpoint', 'list'], additionalEnvVars);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
list: (): Promise<azdataExt.AzdataOutput<azdataExt.DcConfigListResult[]>> => {
|
||||
return this.executeCommand<azdataExt.DcConfigListResult[]>(['arc', 'dc', 'config', 'list']);
|
||||
list: (additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<azdataExt.DcConfigListResult[]>> => {
|
||||
return this.executeCommand<azdataExt.DcConfigListResult[]>(['arc', 'dc', 'config', 'list'], additionalEnvVars);
|
||||
},
|
||||
show: (): Promise<azdataExt.AzdataOutput<azdataExt.DcConfigShowResult>> => {
|
||||
return this.executeCommand<azdataExt.DcConfigShowResult>(['arc', 'dc', 'config', 'show']);
|
||||
show: (additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<azdataExt.DcConfigShowResult>> => {
|
||||
return this.executeCommand<azdataExt.DcConfigShowResult>(['arc', 'dc', 'config', 'show'], additionalEnvVars);
|
||||
}
|
||||
}
|
||||
},
|
||||
postgres: {
|
||||
server: {
|
||||
delete: (name: string): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
return this.executeCommand<void>(['arc', 'postgres', 'server', 'delete', '-n', name, '--force']);
|
||||
delete: (name: string, additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
return this.executeCommand<void>(['arc', 'postgres', 'server', 'delete', '-n', name, '--force'], additionalEnvVars);
|
||||
},
|
||||
list: (): Promise<azdataExt.AzdataOutput<azdataExt.PostgresServerListResult[]>> => {
|
||||
return this.executeCommand<azdataExt.PostgresServerListResult[]>(['arc', 'postgres', 'server', 'list']);
|
||||
list: (additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<azdataExt.PostgresServerListResult[]>> => {
|
||||
return this.executeCommand<azdataExt.PostgresServerListResult[]>(['arc', 'postgres', 'server', 'list'], additionalEnvVars);
|
||||
},
|
||||
show: (name: string): Promise<azdataExt.AzdataOutput<azdataExt.PostgresServerShowResult>> => {
|
||||
return this.executeCommand<azdataExt.PostgresServerShowResult>(['arc', 'postgres', 'server', 'show', '-n', name]);
|
||||
show: (name: string, additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<azdataExt.PostgresServerShowResult>> => {
|
||||
return this.executeCommand<azdataExt.PostgresServerShowResult>(['arc', 'postgres', 'server', 'show', '-n', name], additionalEnvVars);
|
||||
},
|
||||
edit: (
|
||||
name: string,
|
||||
@@ -119,7 +119,7 @@ export class AzdataTool implements azdataExt.IAzdataApi {
|
||||
workers?: number
|
||||
},
|
||||
engineVersion?: string,
|
||||
additionalEnvVars?: { [key: string]: string }): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
const argsArray = ['arc', 'postgres', 'server', 'edit', '-n', name];
|
||||
if (args.adminPassword) { argsArray.push('--admin-password'); }
|
||||
if (args.coresLimit) { argsArray.push('--cores-limit', args.coresLimit); }
|
||||
@@ -139,14 +139,14 @@ export class AzdataTool implements azdataExt.IAzdataApi {
|
||||
},
|
||||
sql: {
|
||||
mi: {
|
||||
delete: (name: string): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
return this.executeCommand<void>(['arc', 'sql', 'mi', 'delete', '-n', name]);
|
||||
delete: (name: string, additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
return this.executeCommand<void>(['arc', 'sql', 'mi', 'delete', '-n', name], additionalEnvVars);
|
||||
},
|
||||
list: (): Promise<azdataExt.AzdataOutput<azdataExt.SqlMiListResult[]>> => {
|
||||
return this.executeCommand<azdataExt.SqlMiListResult[]>(['arc', 'sql', 'mi', 'list']);
|
||||
list: (additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<azdataExt.SqlMiListResult[]>> => {
|
||||
return this.executeCommand<azdataExt.SqlMiListResult[]>(['arc', 'sql', 'mi', 'list'], additionalEnvVars);
|
||||
},
|
||||
show: (name: string): Promise<azdataExt.AzdataOutput<azdataExt.SqlMiShowResult>> => {
|
||||
return this.executeCommand<azdataExt.SqlMiShowResult>(['arc', 'sql', 'mi', 'show', '-n', name]);
|
||||
show: (name: string, additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<azdataExt.SqlMiShowResult>> => {
|
||||
return this.executeCommand<azdataExt.SqlMiShowResult>(['arc', 'sql', 'mi', 'show', '-n', name], additionalEnvVars);
|
||||
},
|
||||
edit: (
|
||||
name: string,
|
||||
@@ -156,21 +156,23 @@ export class AzdataTool implements azdataExt.IAzdataApi {
|
||||
memoryLimit?: string,
|
||||
memoryRequest?: string,
|
||||
noWait?: boolean,
|
||||
}): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
},
|
||||
additionalEnvVars?: azdataExt.AdditionalEnvVars
|
||||
): Promise<azdataExt.AzdataOutput<void>> => {
|
||||
const argsArray = ['arc', 'sql', 'mi', 'edit', '-n', name];
|
||||
if (args.coresLimit) { argsArray.push('--cores-limit', args.coresLimit); }
|
||||
if (args.coresRequest) { argsArray.push('--cores-request', args.coresRequest); }
|
||||
if (args.memoryLimit) { argsArray.push('--memory-limit', args.memoryLimit); }
|
||||
if (args.memoryRequest) { argsArray.push('--memory-request', args.memoryRequest); }
|
||||
if (args.noWait) { argsArray.push('--no-wait'); }
|
||||
return this.executeCommand<void>(argsArray);
|
||||
return this.executeCommand<void>(argsArray, additionalEnvVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public login(endpoint: string, username: string, password: string): Promise<azdataExt.AzdataOutput<void>> {
|
||||
return this.executeCommand<void>(['login', '-e', endpoint, '-u', username], { 'AZDATA_PASSWORD': password });
|
||||
public login(endpoint: string, username: string, password: string, additionalEnvVars: azdataExt.AdditionalEnvVars = {}): Promise<azdataExt.AzdataOutput<void>> {
|
||||
return this.executeCommand<void>(['login', '-e', endpoint, '-u', username], Object.assign({}, additionalEnvVars, { 'AZDATA_PASSWORD': password }));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +190,7 @@ export class AzdataTool implements azdataExt.IAzdataApi {
|
||||
};
|
||||
}
|
||||
|
||||
public async executeCommand<R>(args: string[], additionalEnvVars?: { [key: string]: string }): Promise<azdataExt.AzdataOutput<R>> {
|
||||
public async executeCommand<R>(args: string[], additionalEnvVars?: azdataExt.AdditionalEnvVars): Promise<azdataExt.AzdataOutput<R>> {
|
||||
try {
|
||||
const output = JSON.parse((await executeAzdataCommand(`"${this._path}"`, args.concat(['--output', 'json']), additionalEnvVars)).stdout);
|
||||
return {
|
||||
@@ -609,7 +611,7 @@ async function discoverLatestStableAzdataVersionDarwin(): Promise<SemVer> {
|
||||
return new SemVer(azdataPackageVersionInfo.versions.stable);
|
||||
}
|
||||
|
||||
async function executeAzdataCommand(command: string, args: string[], additionalEnvVars: { [key: string]: string } = {}): Promise<ProcessOutput> {
|
||||
async function executeAzdataCommand(command: string, args: string[], additionalEnvVars: azdataExt.AdditionalEnvVars = {}): Promise<ProcessOutput> {
|
||||
additionalEnvVars = Object.assign(additionalEnvVars, { 'ACCEPT_EULA': 'yes' });
|
||||
const debug = vscode.workspace.getConfiguration(azdataConfigSection).get(debugConfigKey);
|
||||
if (debug) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AdditionalEnvVars } from 'azdata-ext';
|
||||
import * as cp from 'child_process';
|
||||
import * as sudo from 'sudo-prompt';
|
||||
import * as loc from '../localizedConstants';
|
||||
@@ -47,7 +48,7 @@ export type ProcessOutput = { stdout: string, stderr: string };
|
||||
* @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
|
||||
*/
|
||||
export async function executeCommand(command: string, args: string[], additionalEnvVars?: { [key: string]: string },): Promise<ProcessOutput> {
|
||||
export async function executeCommand(command: string, args: string[], additionalEnvVars?: AdditionalEnvVars): Promise<ProcessOutput> {
|
||||
return new Promise((resolve, reject) => {
|
||||
Logger.log(loc.executingCommand(command, args));
|
||||
const stdoutBuffers: Buffer[] = [];
|
||||
|
||||
@@ -18,9 +18,7 @@ export class AzdataToolService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the localAzdata that was last saved
|
||||
*
|
||||
* @param memento The memento that stores the localAzdata object
|
||||
* Sets the localAzdata object to be used for azdata operations
|
||||
*/
|
||||
set localAzdata(azdata: IAzdataTool | undefined) {
|
||||
this._localAzdata = azdata;
|
||||
|
||||
30
extensions/azdata/src/typings/azdata-ext.d.ts
vendored
30
extensions/azdata/src/typings/azdata-ext.d.ts
vendored
@@ -16,6 +16,8 @@ declare module 'azdata-ext' {
|
||||
name = 'Microsoft.azdata'
|
||||
}
|
||||
|
||||
export type AdditionalEnvVars = { [key: string]: string};
|
||||
|
||||
export interface ErrorWithLink extends Error {
|
||||
messageWithLink: string;
|
||||
}
|
||||
@@ -233,20 +235,20 @@ declare module 'azdata-ext' {
|
||||
export interface IAzdataApi {
|
||||
arc: {
|
||||
dc: {
|
||||
create(namespace: string, name: string, connectivityMode: string, resourceGroup: string, location: string, subscription: string, profileName?: string, storageClass?: string): Promise<AzdataOutput<void>>,
|
||||
create(namespace: string, name: string, connectivityMode: string, resourceGroup: string, location: string, subscription: string, profileName?: string, storageClass?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<void>>,
|
||||
endpoint: {
|
||||
list(): Promise<AzdataOutput<DcEndpointListResult[]>>
|
||||
list(additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<DcEndpointListResult[]>>
|
||||
},
|
||||
config: {
|
||||
list(): Promise<AzdataOutput<DcConfigListResult[]>>,
|
||||
show(): Promise<AzdataOutput<DcConfigShowResult>>
|
||||
list(additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<DcConfigListResult[]>>,
|
||||
show(additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<DcConfigShowResult>>
|
||||
}
|
||||
},
|
||||
postgres: {
|
||||
server: {
|
||||
delete(name: string): Promise<AzdataOutput<void>>,
|
||||
list(): Promise<AzdataOutput<PostgresServerListResult[]>>,
|
||||
show(name: string): Promise<AzdataOutput<PostgresServerShowResult>>,
|
||||
delete(name: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<void>>,
|
||||
list(additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<PostgresServerListResult[]>>,
|
||||
show(name: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<PostgresServerShowResult>>,
|
||||
edit(
|
||||
name: string,
|
||||
args: {
|
||||
@@ -263,14 +265,15 @@ declare module 'azdata-ext' {
|
||||
workers?: number
|
||||
},
|
||||
engineVersion?: string,
|
||||
additionalEnvVars?: { [key: string]: string }): Promise<AzdataOutput<void>>
|
||||
additionalEnvVars?: AdditionalEnvVars
|
||||
): Promise<AzdataOutput<void>>
|
||||
}
|
||||
},
|
||||
sql: {
|
||||
mi: {
|
||||
delete(name: string): Promise<AzdataOutput<void>>,
|
||||
list(): Promise<AzdataOutput<SqlMiListResult[]>>,
|
||||
show(name: string): Promise<AzdataOutput<SqlMiShowResult>>,
|
||||
delete(name: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<void>>,
|
||||
list(additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<SqlMiListResult[]>>,
|
||||
show(name: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<SqlMiShowResult>>,
|
||||
edit(
|
||||
name: string,
|
||||
args: {
|
||||
@@ -279,13 +282,14 @@ declare module 'azdata-ext' {
|
||||
memoryLimit?: string,
|
||||
memoryRequest?: string,
|
||||
noWait?: boolean,
|
||||
}
|
||||
},
|
||||
additionalEnvVars?: AdditionalEnvVars
|
||||
): Promise<AzdataOutput<void>>
|
||||
}
|
||||
}
|
||||
},
|
||||
getPath(): Promise<string>,
|
||||
login(endpoint: string, username: string, password: string): Promise<AzdataOutput<any>>,
|
||||
login(endpoint: string, username: string, password: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzdataOutput<any>>,
|
||||
/**
|
||||
* The semVersion corresponding to this installation of azdata. version() method should have been run
|
||||
* before fetching this value to ensure that correct value is returned. This is almost always correct unless
|
||||
|
||||
Reference in New Issue
Block a user