mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-04 09:35:38 -05:00
Arc updates for March release (#14970)
* Updated Postgres Spec for where to find engine version, removed calling calling -ev in edit commands (#14735) * Added spec.engine.version, took out calling engine version with edit calls * Added text wrong place * missed updates * PR fix * Update Arc Postgres troubleshooting notebook Co-authored-by: Brian Bergeron <brberger@microsoft.com> * Remove AzdataSession from azdata commands (#14856) * remove session * Add in controller-context support * Revert "Add in controller-context support" This reverts commit 3b39b968efbf6054041cb01cb2d8443532643a82. * Add azdataContext to login * Undo book change * Undo change correctly * Add controller context support (#14862) * remove session * Add in controller-context support * Add params to fake * Fix tests * Add info and placeholder for controller URL/name (#14887) * Add info and placeholder for controller URL * add period + update name * update memento and allow editing of namespace/URL * vBump * vBump * Fix tests Co-authored-by: nasc17 <69922333+nasc17@users.noreply.github.com> Co-authored-by: Brian Bergeron <brian.e.bergeron@gmail.com> Co-authored-by: Brian Bergeron <brberger@microsoft.com>
This commit is contained in:
@@ -51,7 +51,7 @@ describe('KubeUtils', function (): void {
|
||||
contexts[1].name.should.equal('kubernetes-admin@kubernetes', `test: ${testName} failed`);
|
||||
contexts[1].isCurrentContext.should.be.false(`test: ${testName} failed`);
|
||||
};
|
||||
verifyContexts(await getKubeConfigClusterContexts(configFile), 'getKubeConfigClusterContexts');
|
||||
verifyContexts(getKubeConfigClusterContexts(configFile), 'getKubeConfigClusterContexts');
|
||||
});
|
||||
it('throws error when unable to load config file', async () => {
|
||||
const error = new Error('unknown error accessing file');
|
||||
|
||||
@@ -23,9 +23,9 @@ export class FakeAzdataApi implements azdataExt.IAzdataApi {
|
||||
},
|
||||
postgres: {
|
||||
server: {
|
||||
postgresInstances: [],
|
||||
postgresInstances: <azdataExt.PostgresServerListResult[]>[],
|
||||
delete(_name: string): Promise<azdataExt.AzdataOutput<void>> { throw new Error('Method not implemented.'); },
|
||||
async list(): Promise<azdataExt.AzdataOutput<azdataExt.PostgresServerListResult[]>> { return <any>{ result: this.postgresInstances }; },
|
||||
async list(): Promise<azdataExt.AzdataOutput<azdataExt.PostgresServerListResult[]>> { return { result: this.postgresInstances, logs: [], stdout: [], stderr: [] }; },
|
||||
show(_name: string): Promise<azdataExt.AzdataOutput<azdataExt.PostgresServerShowResult>> { throw new Error('Method not implemented.'); },
|
||||
edit(
|
||||
_name: string,
|
||||
@@ -42,16 +42,15 @@ export class FakeAzdataApi implements azdataExt.IAzdataApi {
|
||||
replaceEngineSettings?: boolean,
|
||||
workers?: number
|
||||
},
|
||||
_engineVersion?: string,
|
||||
_additionalEnvVars?: azdataExt.AdditionalEnvVars
|
||||
): Promise<azdataExt.AzdataOutput<void>> { throw new Error('Method not implemented.'); }
|
||||
}
|
||||
},
|
||||
sql: {
|
||||
mi: {
|
||||
miaaInstances: [],
|
||||
miaaInstances: <azdataExt.SqlMiListResult[]>[],
|
||||
delete(_name: string): Promise<azdataExt.AzdataOutput<void>> { throw new Error('Method not implemented.'); },
|
||||
async list(): Promise<azdataExt.AzdataOutput<azdataExt.SqlMiListResult[]>> { return <any>{ result: this.miaaInstances }; },
|
||||
async list(): Promise<azdataExt.AzdataOutput<azdataExt.SqlMiListResult[]>> { return { logs: [], stdout: [], stderr: [], result: this.miaaInstances }; },
|
||||
show(_name: string): Promise<azdataExt.AzdataOutput<azdataExt.SqlMiShowResult>> { throw new Error('Method not implemented.'); },
|
||||
edit(
|
||||
_name: string,
|
||||
@@ -66,17 +65,14 @@ export class FakeAzdataApi implements azdataExt.IAzdataApi {
|
||||
}
|
||||
};
|
||||
|
||||
// public postgresInstances: azdataExt.PostgresServerListResult[] = [];
|
||||
public set postgresInstances(instances: azdataExt.PostgresServerListResult[]) {
|
||||
this._arcApi.postgres.server.postgresInstances = <any>instances;
|
||||
this._arcApi.postgres.server.postgresInstances = instances;
|
||||
}
|
||||
|
||||
public set miaaInstances(instances: azdataExt.SqlMiListResult[]) {
|
||||
this._arcApi.sql.mi.miaaInstances = <any>instances;
|
||||
this._arcApi.sql.mi.miaaInstances = instances;
|
||||
}
|
||||
|
||||
// public miaaInstances: azdataExt.SqlMiListResult[] = [];
|
||||
|
||||
//
|
||||
// API Implementation
|
||||
//
|
||||
@@ -86,12 +82,9 @@ export class FakeAzdataApi implements azdataExt.IAzdataApi {
|
||||
getPath(): Promise<string> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
login(_endpoint: string, _username: string, _password: string): Promise<azdataExt.AzdataOutput<void>> {
|
||||
login(_endpointOrNamespace: azdataExt.EndpointOrNamespace, _username: string, _password: string, _additionalEnvVars: azdataExt.AdditionalEnvVars = {}, _azdataContext?: string): Promise<azdataExt.AzdataOutput<void>> {
|
||||
return <any>undefined;
|
||||
}
|
||||
acquireSession(_endpoint: string, _username: string, _password: string): Promise<azdataExt.AzdataSession> {
|
||||
return Promise.resolve({ dispose: () => { } });
|
||||
}
|
||||
version(): Promise<azdataExt.AzdataOutput<string>> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { AzureArcTreeDataProvider } from '../../ui/tree/azureArcTreeDataProvider
|
||||
export class FakeControllerModel extends ControllerModel {
|
||||
|
||||
constructor(treeDataProvider?: AzureArcTreeDataProvider, info?: Partial<ControllerInfo>, password?: string) {
|
||||
const _info: ControllerInfo = Object.assign({ id: uuid(), url: '', kubeConfigFilePath: '', kubeClusterContext: '', name: '', username: '', rememberPassword: false, resources: [] }, info);
|
||||
const _info: ControllerInfo = Object.assign({ id: uuid(), endpoint: '', kubeConfigFilePath: '', kubeClusterContext: '', name: '', namespace: '', username: '', rememberPassword: false, resources: [] }, info);
|
||||
super(treeDataProvider!, _info, password);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,20 @@ interface ExtensionGlobalMemento extends vscode.Memento {
|
||||
setKeysForSync(keys: string[]): void;
|
||||
}
|
||||
|
||||
function getDefaultControllerInfo(): ControllerInfo {
|
||||
return {
|
||||
id: uuid(),
|
||||
endpoint: '127.0.0.1',
|
||||
kubeConfigFilePath: '/path/to/.kube/config',
|
||||
kubeClusterContext: 'currentCluster',
|
||||
username: 'admin',
|
||||
name: 'arc',
|
||||
namespace: 'arc-ns',
|
||||
rememberPassword: true,
|
||||
resources: []
|
||||
};
|
||||
}
|
||||
|
||||
describe('ControllerModel', function (): void {
|
||||
afterEach(function (): void {
|
||||
sinon.restore();
|
||||
@@ -39,15 +53,15 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
beforeEach(function (): void {
|
||||
sinon.stub(ConnectToControllerDialog.prototype, 'showDialog');
|
||||
sinon.stub(kubeUtils, 'getKubeConfigClusterContexts').resolves([{ name: 'currentCluster', isCurrentContext: true }]);
|
||||
sinon.stub(kubeUtils, 'getKubeConfigClusterContexts').returns([{ 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> {
|
||||
// Returning an undefined model here indicates that the dialog closed without clicking "Ok" - usually through the user clicking "Cancel"
|
||||
sinon.stub(ConnectToControllerDialog.prototype, 'waitForClose').returns(Promise.resolve(undefined));
|
||||
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 should(model.acquireAzdataSession()).be.rejectedWith(new UserCancelledError(loc.userCancelledError));
|
||||
const model = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), getDefaultControllerInfo());
|
||||
await should(model.login()).be.rejectedWith(new UserCancelledError(loc.userCancelledError));
|
||||
});
|
||||
|
||||
it('Reads password from cred store', async function (): Promise<void> {
|
||||
@@ -62,13 +76,13 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
const azdataExtApiMock = TypeMoq.Mock.ofType<azdataExt.IExtension>();
|
||||
const azdataMock = TypeMoq.Mock.ofType<azdataExt.IAzdataApi>();
|
||||
azdataMock.setup(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataMock.setup(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataExtApiMock.setup(x => x.azdata).returns(() => azdataMock.object);
|
||||
sinon.stub(vscode.extensions, 'getExtension').returns(<any>{ exports: azdataExtApiMock.object });
|
||||
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: [] });
|
||||
const model = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), getDefaultControllerInfo());
|
||||
|
||||
await model.acquireAzdataSession();
|
||||
azdataMock.verify(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password, TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
await model.login();
|
||||
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> {
|
||||
@@ -83,18 +97,18 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
const azdataExtApiMock = TypeMoq.Mock.ofType<azdataExt.IExtension>();
|
||||
const azdataMock = TypeMoq.Mock.ofType<azdataExt.IAzdataApi>();
|
||||
azdataMock.setup(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataMock.setup(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataExtApiMock.setup(x => x.azdata).returns(() => azdataMock.object);
|
||||
sinon.stub(vscode.extensions, 'getExtension').returns(<any>{ exports: azdataExtApiMock.object });
|
||||
|
||||
// Set up dialog to return new model with our password
|
||||
const newModel = 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: [] }, password);
|
||||
const newModel = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), getDefaultControllerInfo(), password);
|
||||
sinon.stub(ConnectToControllerDialog.prototype, 'waitForClose').returns(Promise.resolve({ controllerModel: newModel, password: password }));
|
||||
|
||||
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: [] });
|
||||
const model = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), getDefaultControllerInfo());
|
||||
|
||||
await model.acquireAzdataSession();
|
||||
azdataMock.verify(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password, TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||
await model.login();
|
||||
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> {
|
||||
@@ -108,19 +122,19 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
const azdataExtApiMock = TypeMoq.Mock.ofType<azdataExt.IExtension>();
|
||||
const azdataMock = TypeMoq.Mock.ofType<azdataExt.IAzdataApi>();
|
||||
azdataMock.setup(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataMock.setup(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataExtApiMock.setup(x => x.azdata).returns(() => azdataMock.object);
|
||||
sinon.stub(vscode.extensions, 'getExtension').returns(<any>{ exports: azdataExtApiMock.object });
|
||||
|
||||
// Set up dialog to return new model with our new password from the reprompt
|
||||
const newModel = 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: [] }, password);
|
||||
const newModel = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), getDefaultControllerInfo(), password);
|
||||
const waitForCloseStub = sinon.stub(ConnectToControllerDialog.prototype, 'waitForClose').returns(Promise.resolve({ controllerModel: newModel, password: password }));
|
||||
|
||||
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: [] });
|
||||
const model = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), getDefaultControllerInfo());
|
||||
|
||||
await model.acquireAzdataSession(true);
|
||||
await model.login(true);
|
||||
should(waitForCloseStub.called).be.true('waitForClose should have been called');
|
||||
azdataMock.verify(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password, TypeMoq.It.isAny()), 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> {
|
||||
@@ -134,20 +148,20 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
const azdataExtApiMock = TypeMoq.Mock.ofType<azdataExt.IExtension>();
|
||||
const azdataMock = TypeMoq.Mock.ofType<azdataExt.IAzdataApi>();
|
||||
azdataMock.setup(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataMock.setup(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataExtApiMock.setup(x => x.azdata).returns(() => azdataMock.object);
|
||||
sinon.stub(vscode.extensions, 'getExtension').returns(<any>{ exports: azdataExtApiMock.object });
|
||||
|
||||
// Set up dialog to return new model with our new password from the reprompt
|
||||
const newModel = 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: [] }, password);
|
||||
const newModel = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), getDefaultControllerInfo(), password);
|
||||
const waitForCloseStub = sinon.stub(ConnectToControllerDialog.prototype, 'waitForClose').returns(Promise.resolve({ controllerModel: newModel, password: password }));
|
||||
|
||||
// Set up original model with a password
|
||||
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: [] }, 'originalPassword');
|
||||
const model = new ControllerModel(new AzureArcTreeDataProvider(mockExtensionContext.object), getDefaultControllerInfo(), 'originalPassword');
|
||||
|
||||
await model.acquireAzdataSession(true);
|
||||
await model.login(true);
|
||||
should(waitForCloseStub.called).be.true('waitForClose should have been called');
|
||||
azdataMock.verify(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), password, TypeMoq.It.isAny()), 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> {
|
||||
@@ -162,7 +176,7 @@ describe('ControllerModel', function (): void {
|
||||
|
||||
const azdataExtApiMock = TypeMoq.Mock.ofType<azdataExt.IExtension>();
|
||||
const azdataMock = TypeMoq.Mock.ofType<azdataExt.IAzdataApi>();
|
||||
azdataMock.setup(x => x.acquireSession(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataMock.setup(x => x.login(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => <any>Promise.resolve(undefined));
|
||||
azdataExtApiMock.setup(x => x.azdata).returns(() => azdataMock.object);
|
||||
sinon.stub(vscode.extensions, 'getExtension').returns(<any>{ exports: azdataExtApiMock.object });
|
||||
|
||||
@@ -170,27 +184,19 @@ describe('ControllerModel', function (): void {
|
||||
const originalPassword = 'originalPassword';
|
||||
const model = new ControllerModel(
|
||||
treeDataProvider,
|
||||
{
|
||||
id: uuid(),
|
||||
url: '127.0.0.1',
|
||||
kubeConfigFilePath: '/path/to/.kube/config',
|
||||
kubeClusterContext: 'currentCluster',
|
||||
username: 'admin',
|
||||
name: 'arc',
|
||||
rememberPassword: false,
|
||||
resources: []
|
||||
},
|
||||
getDefaultControllerInfo(),
|
||||
originalPassword
|
||||
);
|
||||
await treeDataProvider.addOrUpdateController(model, originalPassword);
|
||||
|
||||
const newInfo: ControllerInfo = {
|
||||
id: model.info.id, // The ID stays the same since we're just re-entering information for the same model
|
||||
url: 'newUrl',
|
||||
endpoint: 'newUrl',
|
||||
kubeConfigFilePath: '/path/to/.kube/config',
|
||||
kubeClusterContext: 'currentCluster',
|
||||
username: 'newUser',
|
||||
name: 'newName',
|
||||
namespace: 'newNamespace',
|
||||
rememberPassword: true,
|
||||
resources: []
|
||||
};
|
||||
@@ -203,7 +209,7 @@ describe('ControllerModel', function (): void {
|
||||
const waitForCloseStub = sinon.stub(ConnectToControllerDialog.prototype, 'waitForClose').returns(Promise.resolve(
|
||||
{ controllerModel: newModel, password: newPassword }));
|
||||
|
||||
await model.acquireAzdataSession(true);
|
||||
await model.login(true);
|
||||
should(waitForCloseStub.called).be.true('waitForClose should have been called');
|
||||
should((await treeDataProvider.getChildren()).length).equal(1, 'Tree Data provider should still only have 1 node');
|
||||
should(model.info).deepEqual(newInfo, 'Model info should have been updated');
|
||||
|
||||
@@ -40,7 +40,8 @@ export const FakePostgresServerShowOutput: azdataExt.AzdataOutput<azdataExt.Post
|
||||
extensions: [{ name: '' }],
|
||||
settings: {
|
||||
default: { ['']: '' }
|
||||
}
|
||||
},
|
||||
version: ''
|
||||
},
|
||||
scale: {
|
||||
shards: 0,
|
||||
@@ -114,7 +115,7 @@ describe('PostgresModel', function (): void {
|
||||
controllerModel = new FakeControllerModel();
|
||||
|
||||
//Stub calling azdata login and acquiring session
|
||||
sinon.stub(controllerModel, 'acquireAzdataSession').returns(Promise.resolve(vscode.Disposable.from()));
|
||||
sinon.stub(controllerModel, 'login').returns(Promise.resolve());
|
||||
|
||||
// Stub the azdata CLI API
|
||||
azdataApi = new FakeAzdataApi();
|
||||
|
||||
@@ -38,7 +38,8 @@ export const FakePostgresServerShowOutput: azdataExt.AzdataOutput<azdataExt.Post
|
||||
extensions: [{ name: '' }],
|
||||
settings: {
|
||||
default: { ['']: '' }
|
||||
}
|
||||
},
|
||||
version: '12'
|
||||
},
|
||||
scale: {
|
||||
shards: 0,
|
||||
@@ -121,7 +122,7 @@ describe('postgresConnectionStringsPage', function (): void {
|
||||
controllerModel = new FakeControllerModel();
|
||||
|
||||
//Stub calling azdata login and acquiring session
|
||||
sinon.stub(controllerModel, 'acquireAzdataSession').returns(Promise.resolve(vscode.Disposable.from()));
|
||||
sinon.stub(controllerModel, 'login').returns(Promise.resolve());
|
||||
|
||||
// Setup PostgresModel
|
||||
const postgresResource: PGResourceInfo = { name: 'pgt', resourceType: '' };
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('postgresOverviewPage', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
sinon.stub(utils, 'promptForInstanceDeletion').returns(Promise.resolve(true));
|
||||
sinon.stub(controllerModel, 'acquireAzdataSession').returns(Promise.resolve(vscode.Disposable.from()));
|
||||
sinon.stub(controllerModel, 'login').returns(Promise.resolve());
|
||||
refreshTreeNode = sinon.stub(controllerModel, 'refreshTreeNode');
|
||||
});
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ describe('ConnectControllerDialog', function (): void {
|
||||
|
||||
(<{ info: ControllerInfo | undefined, description: string }[]>[
|
||||
{ info: undefined, description: 'all input' },
|
||||
{ info: { url: '127.0.0.1' }, description: 'all but URL' },
|
||||
{ info: { url: '127.0.0.1', username: 'sa' }, description: 'all but URL and password' }]).forEach(test => {
|
||||
{ info: { endpoint: '127.0.0.1' }, description: 'all but URL' },
|
||||
{ info: { endpoint: '127.0.0.1', username: 'sa' }, description: 'all but URL and password' }]).forEach(test => {
|
||||
it(`Validate returns false when ${test.description} is empty`, async function (): Promise<void> {
|
||||
const connectControllerDialog = new ConnectToControllerDialog(undefined!);
|
||||
connectControllerDialog.showDialog(test.info, undefined);
|
||||
@@ -32,7 +32,7 @@ describe('ConnectControllerDialog', function (): void {
|
||||
it('validate returns false if controller refresh fails', async function (): Promise<void> {
|
||||
sinon.stub(ControllerModel.prototype, 'refresh').returns(Promise.reject('Controller refresh failed'));
|
||||
const connectControllerDialog = new ConnectToControllerDialog(undefined!);
|
||||
const info = { id: uuid(), url: 'https://127.0.0.1:30080', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', username: 'sa', rememberPassword: true, resources: [] };
|
||||
const info: ControllerInfo = { id: uuid(), endpoint: 'https://127.0.0.1:30080', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', namespace: 'arc-ns', username: 'sa', rememberPassword: true, resources: [] };
|
||||
connectControllerDialog.showDialog(info, 'pwd');
|
||||
await connectControllerDialog.isInitialized;
|
||||
const validateResult = await connectControllerDialog.validate();
|
||||
@@ -41,36 +41,36 @@ describe('ConnectControllerDialog', function (): void {
|
||||
|
||||
it('validate replaces http with https', async function (): Promise<void> {
|
||||
await validateConnectControllerDialog(
|
||||
{ id: uuid(), url: 'http://127.0.0.1:30081', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', username: 'sa', rememberPassword: true, resources: [] },
|
||||
{ id: uuid(), endpoint: 'http://127.0.0.1:30081', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', namespace: 'arc-ns', username: 'sa', rememberPassword: true, resources: [] },
|
||||
'https://127.0.0.1:30081');
|
||||
});
|
||||
|
||||
it('validate appends https if missing', async function (): Promise<void> {
|
||||
await validateConnectControllerDialog({ id: uuid(), url: '127.0.0.1:30080', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', username: 'sa', rememberPassword: true, resources: [] },
|
||||
await validateConnectControllerDialog({ id: uuid(), endpoint: '127.0.0.1:30080', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', namespace: 'arc-ns', username: 'sa', rememberPassword: true, resources: [] },
|
||||
'https://127.0.0.1:30080');
|
||||
});
|
||||
|
||||
it('validate appends default port if missing', async function (): Promise<void> {
|
||||
await validateConnectControllerDialog({ id: uuid(), url: 'https://127.0.0.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', username: 'sa', rememberPassword: true, resources: [] },
|
||||
await validateConnectControllerDialog({ id: uuid(), endpoint: 'https://127.0.0.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', namespace: 'arc-ns', username: 'sa', rememberPassword: true, resources: [] },
|
||||
'https://127.0.0.1:30080');
|
||||
});
|
||||
|
||||
it('validate appends both port and https if missing', async function (): Promise<void> {
|
||||
await validateConnectControllerDialog({ id: uuid(), url: '127.0.0.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', username: 'sa', rememberPassword: true, resources: [] },
|
||||
await validateConnectControllerDialog({ id: uuid(), endpoint: '127.0.0.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', namespace: 'arc-ns', username: 'sa', rememberPassword: true, resources: [] },
|
||||
'https://127.0.0.1:30080');
|
||||
});
|
||||
|
||||
for (const name of ['', undefined]) {
|
||||
it.skip(`validate display name gets set to arc instance name for user chosen name of:${name}`, async function (): Promise<void> {
|
||||
await validateConnectControllerDialog(
|
||||
{ id: uuid(), url: 'http://127.0.0.1:30081', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: name!, username: 'sa', rememberPassword: true, resources: [] },
|
||||
{ id: uuid(), endpoint: 'http://127.0.0.1:30081', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: name!, namespace: 'arc-ns', username: 'sa', rememberPassword: true, resources: [] },
|
||||
'https://127.0.0.1:30081');
|
||||
});
|
||||
}
|
||||
|
||||
it.skip(`validate display name gets set to default data controller name for user chosen name of:'' and instanceName in explicably returned as undefined from the controller endpoint`, async function (): Promise<void> {
|
||||
await validateConnectControllerDialog(
|
||||
{ id: uuid(), url: 'http://127.0.0.1:30081', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: '', username: 'sa', rememberPassword: true, resources: [] },
|
||||
{ id: uuid(), endpoint: 'http://127.0.0.1:30081', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: '', namespace: 'arc-ns', username: 'sa', rememberPassword: true, resources: [] },
|
||||
'https://127.0.0.1:30081',
|
||||
undefined);
|
||||
});
|
||||
@@ -92,6 +92,6 @@ async function validateConnectControllerDialog(info: ControllerInfo, expectedUrl
|
||||
const validateResult = await connectControllerDialog.validate();
|
||||
should(validateResult).be.true('Validation should have returned true');
|
||||
const model = await connectControllerDialog.waitForClose();
|
||||
should(model?.controllerModel.info.url).equal(expectedUrl);
|
||||
should(model?.controllerModel.info.endpoint).equal(expectedUrl);
|
||||
should(model?.controllerModel.info.name).equal(expectedControllerInfoName);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,20 @@ interface ExtensionGlobalMemento extends vscode.Memento {
|
||||
setKeysForSync(keys: string[]): void;
|
||||
}
|
||||
|
||||
function getDefaultControllerInfo(): ControllerInfo {
|
||||
return {
|
||||
id: uuid(),
|
||||
endpoint: '127.0.0.1',
|
||||
kubeConfigFilePath: '/path/to/.kube/config',
|
||||
kubeClusterContext: 'currentCluster',
|
||||
username: 'sa',
|
||||
name: 'my-arc',
|
||||
namespace: 'arc-ns',
|
||||
rememberPassword: true,
|
||||
resources: []
|
||||
};
|
||||
}
|
||||
|
||||
describe('AzureArcTreeDataProvider tests', function (): void {
|
||||
let treeDataProvider: AzureArcTreeDataProvider;
|
||||
beforeEach(function (): void {
|
||||
@@ -58,7 +72,7 @@ describe('AzureArcTreeDataProvider tests', function (): void {
|
||||
treeDataProvider['_loading'] = false;
|
||||
let children = await treeDataProvider.getChildren();
|
||||
should(children.length).equal(0, 'There initially shouldn\'t be any children');
|
||||
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: [] });
|
||||
const controllerModel = new ControllerModel(treeDataProvider, getDefaultControllerInfo());
|
||||
await treeDataProvider.addOrUpdateController(controllerModel, '');
|
||||
should(children.length).equal(1, 'Controller node should be added correctly');
|
||||
await treeDataProvider.addOrUpdateController(controllerModel, '');
|
||||
@@ -69,12 +83,12 @@ describe('AzureArcTreeDataProvider tests', function (): void {
|
||||
treeDataProvider['_loading'] = false;
|
||||
let children = await treeDataProvider.getChildren();
|
||||
should(children.length).equal(0, 'There initially shouldn\'t be any children');
|
||||
const originalInfo: ControllerInfo = { id: uuid(), url: '127.0.0.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', username: 'sa', rememberPassword: true, resources: [] };
|
||||
const originalInfo: ControllerInfo = getDefaultControllerInfo();
|
||||
const controllerModel = new ControllerModel(treeDataProvider, originalInfo);
|
||||
await treeDataProvider.addOrUpdateController(controllerModel, '');
|
||||
should(children.length).equal(1, 'Controller node should be added correctly');
|
||||
should((<ControllerTreeNode>children[0]).model.info).deepEqual(originalInfo);
|
||||
const newInfo = { id: originalInfo.id, url: '1.1.1.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'new-name', username: 'admin', rememberPassword: false, resources: [] };
|
||||
const newInfo: ControllerInfo = { id: originalInfo.id, endpoint: '1.1.1.1', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'new-name', namespace: 'new-namespace', username: 'admin', rememberPassword: false, resources: [] };
|
||||
const controllerModel2 = new ControllerModel(treeDataProvider, newInfo);
|
||||
await treeDataProvider.addOrUpdateController(controllerModel2, '');
|
||||
should(children.length).equal(1, 'Shouldn\'t add duplicate controller node');
|
||||
@@ -109,8 +123,8 @@ 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');
|
||||
sinon.stub(kubeUtils, 'getKubeConfigClusterContexts').returns([{ name: 'currentCluster', isCurrentContext: true }]);
|
||||
const controllerModel = new ControllerModel(treeDataProvider, getDefaultControllerInfo(), 'mypassword');
|
||||
await treeDataProvider.addOrUpdateController(controllerModel, '');
|
||||
const controllerNode = treeDataProvider.getControllerNode(controllerModel);
|
||||
const children = await treeDataProvider.getChildren(controllerNode);
|
||||
@@ -123,8 +137,10 @@ describe('AzureArcTreeDataProvider tests', function (): void {
|
||||
describe('removeController', function (): void {
|
||||
it('removing a controller should work as expected', async function (): Promise<void> {
|
||||
treeDataProvider['_loading'] = false;
|
||||
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: [] });
|
||||
const controllerModel2 = new ControllerModel(treeDataProvider, { id: uuid(), url: '127.0.0.2', kubeConfigFilePath: '/path/to/.kube/config', kubeClusterContext: 'currentCluster', name: 'my-arc', username: 'cloudsa', rememberPassword: true, resources: [] });
|
||||
const controllerModel = new ControllerModel(treeDataProvider, getDefaultControllerInfo());
|
||||
const info2 = getDefaultControllerInfo();
|
||||
info2.username = 'cloudsa';
|
||||
const controllerModel2 = new ControllerModel(treeDataProvider, info2);
|
||||
await treeDataProvider.addOrUpdateController(controllerModel, '');
|
||||
await treeDataProvider.addOrUpdateController(controllerModel2, '');
|
||||
const children = <ControllerTreeNode[]>(await treeDataProvider.getChildren());
|
||||
@@ -141,20 +157,20 @@ describe('AzureArcTreeDataProvider tests', function (): void {
|
||||
|
||||
describe('openResourceDashboard', function (): void {
|
||||
it('Opening dashboard for nonexistent controller node throws', async function (): Promise<void> {
|
||||
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: [] });
|
||||
const controllerModel = new ControllerModel(treeDataProvider, getDefaultControllerInfo());
|
||||
const openDashboardPromise = treeDataProvider.openResourceDashboard(controllerModel, ResourceType.sqlManagedInstances, '');
|
||||
await should(openDashboardPromise).be.rejected();
|
||||
});
|
||||
|
||||
it('Opening dashboard for nonexistent resource throws', async function (): Promise<void> {
|
||||
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: [] });
|
||||
const controllerModel = new ControllerModel(treeDataProvider, getDefaultControllerInfo());
|
||||
await treeDataProvider.addOrUpdateController(controllerModel, '');
|
||||
const openDashboardPromise = treeDataProvider.openResourceDashboard(controllerModel, ResourceType.sqlManagedInstances, '');
|
||||
await should(openDashboardPromise).be.rejected();
|
||||
});
|
||||
|
||||
it('Opening dashboard for existing resource node succeeds', async function (): Promise<void> {
|
||||
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: [] });
|
||||
const controllerModel = new ControllerModel(treeDataProvider, getDefaultControllerInfo());
|
||||
const miaaModel = new MiaaModel(controllerModel, { name: 'miaa-1', resourceType: ResourceType.sqlManagedInstances }, undefined!, treeDataProvider);
|
||||
await treeDataProvider.addOrUpdateController(controllerModel, '');
|
||||
const controllerNode = treeDataProvider.getControllerNode(controllerModel)!;
|
||||
|
||||
Reference in New Issue
Block a user