mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Fix broken native command line argument support (#23312)
This commit is contained in:
@@ -30,64 +30,6 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
|||||||
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||||
|
|
||||||
export interface SqlArgs {
|
|
||||||
/**
|
|
||||||
* Used to determine file paths to be opened with SQL Editor.
|
|
||||||
* If provided, we connect the given profile to to it.
|
|
||||||
* More than one files can be passed to connect to provided profile.
|
|
||||||
*/
|
|
||||||
_?: string[];
|
|
||||||
/**
|
|
||||||
* Provide authenticationType to be used.
|
|
||||||
* accepted values: AzureMFA, SqlLogin, Integrated, etc.
|
|
||||||
*/
|
|
||||||
authenticationType?: string
|
|
||||||
/**
|
|
||||||
* Name of database
|
|
||||||
*/
|
|
||||||
database?: string;
|
|
||||||
/**
|
|
||||||
* Name of server
|
|
||||||
*/
|
|
||||||
server?: string;
|
|
||||||
/**
|
|
||||||
* User name/email address
|
|
||||||
*/
|
|
||||||
user?: string;
|
|
||||||
/**
|
|
||||||
* Operation to perform:
|
|
||||||
* accepted values: connect, openConnectionDialog
|
|
||||||
*/
|
|
||||||
command?: string;
|
|
||||||
/**
|
|
||||||
* Name of connection provider,
|
|
||||||
* accepted values: mssql (by default), pgsql, etc.
|
|
||||||
*/
|
|
||||||
provider?: string;
|
|
||||||
/**
|
|
||||||
* Deprecated - used by SSMS - authenticationType should be used instead
|
|
||||||
*/
|
|
||||||
aad?: boolean;
|
|
||||||
/**
|
|
||||||
* Deprecated - used by SSMS - authenticationType should be used instead.
|
|
||||||
*/
|
|
||||||
integrated?: boolean;
|
|
||||||
/**
|
|
||||||
* Whether or not to show dashboard
|
|
||||||
* accepted values: true, false (by default).
|
|
||||||
*/
|
|
||||||
showDashboard?: boolean;
|
|
||||||
/**
|
|
||||||
* Supports providing applicationName that will be used for connection profile app name.
|
|
||||||
*/
|
|
||||||
applicationName?: string;
|
|
||||||
/**
|
|
||||||
* Supports providing advanced connection properties that providers support.
|
|
||||||
* Value must be a json object containing key-value pairs in format: '{"key1":"value1","key2":"value2",...}'
|
|
||||||
*/
|
|
||||||
connectionProperties?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
//#region decorators
|
//#region decorators
|
||||||
|
|
||||||
type PathHandler = (uri: URI) => Promise<boolean>;
|
type PathHandler = (uri: URI) => Promise<boolean>;
|
||||||
@@ -153,7 +95,7 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
|
|||||||
// (null, commandName) => Launch the command with a null connection. If the command implementation needs a connection, it will need to create it.
|
// (null, commandName) => Launch the command with a null connection. If the command implementation needs a connection, it will need to create it.
|
||||||
// (serverName, null) => Connect object explorer and open a new query editor if no file names are passed. If file names are passed, connect their editors to the server.
|
// (serverName, null) => Connect object explorer and open a new query editor if no file names are passed. If file names are passed, connect their editors to the server.
|
||||||
// (null, null) => Prompt for a connection unless there are registered servers
|
// (null, null) => Prompt for a connection unless there are registered servers
|
||||||
public async processCommandLine(args: SqlArgs): Promise<void> {
|
public async processCommandLine(args: NativeParsedArgs): Promise<void> {
|
||||||
let profile: IConnectionProfile = undefined;
|
let profile: IConnectionProfile = undefined;
|
||||||
let commandName = undefined;
|
let commandName = undefined;
|
||||||
if (args) {
|
if (args) {
|
||||||
@@ -296,7 +238,7 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async confirmConnect(args: SqlArgs): Promise<boolean> {
|
private async confirmConnect(args: NativeParsedArgs): Promise<boolean> {
|
||||||
let detail = args && args.server ? localize('connectServerDetail', "This will connect to server {0}", args.server) : '';
|
let detail = args && args.server ? localize('connectServerDetail', "This will connect to server {0}", args.server) : '';
|
||||||
const result = await this.dialogService.confirm({
|
const result = await this.dialogService.confirm({
|
||||||
message: localize('confirmConnect', "Are you sure you want to connect?"),
|
message: localize('confirmConnect', "Are you sure you want to connect?"),
|
||||||
@@ -311,8 +253,8 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseProtocolArgs(uri: URI): SqlArgs {
|
private parseProtocolArgs(uri: URI): NativeParsedArgs {
|
||||||
let args: SqlArgs = querystring.parse(uri.query);
|
let args: NativeParsedArgs = querystring.parse(uri.query);
|
||||||
// Clear out command, not supporting arbitrary command via this path
|
// Clear out command, not supporting arbitrary command via this path
|
||||||
args.command = undefined;
|
args.command = undefined;
|
||||||
return args;
|
return args;
|
||||||
@@ -336,7 +278,7 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readProfileFromArgs(args: SqlArgs) {
|
private readProfileFromArgs(args: NativeParsedArgs) {
|
||||||
let profile = new ConnectionProfile(this._capabilitiesService, null);
|
let profile = new ConnectionProfile(this._capabilitiesService, null);
|
||||||
// We want connection store to use any matching password it finds
|
// We want connection store to use any matching password it finds
|
||||||
profile.savePassword = true;
|
profile.savePassword = true;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import * as TypeMoq from 'typemoq';
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||||
import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
|
import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
|
||||||
import { CommandLineWorkbenchContribution, SqlArgs } from 'sql/workbench/contrib/commandLine/electron-browser/commandLine';
|
import { CommandLineWorkbenchContribution } from 'sql/workbench/contrib/commandLine/electron-browser/commandLine';
|
||||||
import * as Constants from 'sql/platform/connection/common/constants';
|
import * as Constants from 'sql/platform/connection/common/constants';
|
||||||
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
|
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
|
||||||
import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService';
|
import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService';
|
||||||
@@ -35,11 +35,24 @@ import { FileQueryEditorInput } from 'sql/workbench/contrib/query/browser/fileQu
|
|||||||
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
|
||||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||||
|
|
||||||
class TestParsedArgs implements NativeParsedArgs, SqlArgs {
|
class TestParsedArgs implements NativeParsedArgs {
|
||||||
[arg: string]: any;
|
[arg: string]: any;
|
||||||
_: string[];
|
_: string[];
|
||||||
database?: string;
|
|
||||||
|
// Start: SQL Args
|
||||||
|
aad?: boolean;
|
||||||
|
applicationName?: string;
|
||||||
|
authenticationType?: string;
|
||||||
command?: string;
|
command?: string;
|
||||||
|
connectionProperties?: string;
|
||||||
|
database?: string;
|
||||||
|
integrated?: boolean;
|
||||||
|
provider?: string;
|
||||||
|
server?: string;
|
||||||
|
showDashboard?: boolean;
|
||||||
|
user?: string;
|
||||||
|
// End: SQL Args
|
||||||
|
|
||||||
debugBrkPluginHost?: string;
|
debugBrkPluginHost?: string;
|
||||||
debugBrkSearch?: string;
|
debugBrkSearch?: string;
|
||||||
debugId?: string;
|
debugId?: string;
|
||||||
@@ -77,7 +90,6 @@ class TestParsedArgs implements NativeParsedArgs, SqlArgs {
|
|||||||
'prof-startup'?: boolean;
|
'prof-startup'?: boolean;
|
||||||
'prof-startup-prefix'?: string;
|
'prof-startup-prefix'?: string;
|
||||||
'reuse-window'?: boolean;
|
'reuse-window'?: boolean;
|
||||||
server?: string;
|
|
||||||
'show-versions'?: boolean;
|
'show-versions'?: boolean;
|
||||||
'skip-add-to-recently-opened'?: boolean;
|
'skip-add-to-recently-opened'?: boolean;
|
||||||
'skip-getting-started'?: boolean;
|
'skip-getting-started'?: boolean;
|
||||||
@@ -87,16 +99,12 @@ class TestParsedArgs implements NativeParsedArgs, SqlArgs {
|
|||||||
'uninstall-extension'?: string[];
|
'uninstall-extension'?: string[];
|
||||||
'unity-launch'?: boolean; // Always open a new window, except if opening the first window or opening a file or folder as part of the launch.
|
'unity-launch'?: boolean; // Always open a new window, except if opening the first window or opening a file or folder as part of the launch.
|
||||||
'upload-logs'?: string;
|
'upload-logs'?: string;
|
||||||
user?: string;
|
|
||||||
'user-data-dir'?: string;
|
'user-data-dir'?: string;
|
||||||
_urls?: string[];
|
_urls?: string[];
|
||||||
verbose?: boolean;
|
verbose?: boolean;
|
||||||
version?: boolean;
|
version?: boolean;
|
||||||
wait?: boolean;
|
wait?: boolean;
|
||||||
waitMarkerFilePath?: string;
|
waitMarkerFilePath?: string;
|
||||||
authenticationType?: string;
|
|
||||||
applicationName?: string;
|
|
||||||
connectionProperties?: string;
|
|
||||||
}
|
}
|
||||||
suite('commandLineService tests', () => {
|
suite('commandLineService tests', () => {
|
||||||
|
|
||||||
@@ -220,6 +228,30 @@ suite('commandLineService tests', () => {
|
|||||||
connectionManagementService.verifyAll();
|
connectionManagementService.verifyAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('processCommandLine shows dashboard when requested', async () => {
|
||||||
|
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
||||||
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
|
|
||||||
|
const args: TestParsedArgs = new TestParsedArgs();
|
||||||
|
args.server = 'myserver';
|
||||||
|
args.database = 'mydatabase';
|
||||||
|
args.user = 'myuser';
|
||||||
|
args.showDashboard = true;
|
||||||
|
args.authenticationType = Constants.AuthenticationType.SqlLogin;
|
||||||
|
|
||||||
|
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
|
||||||
|
connectionManagementService.setup(c => c.showDashboard(TypeMoq.It.isAny())).verifiable(TypeMoq.Times.atMostOnce());
|
||||||
|
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true).verifiable(TypeMoq.Times.atMostOnce());
|
||||||
|
connectionManagementService.setup(c => c.getConnectionGroups(TypeMoq.It.isAny())).returns(() => []);
|
||||||
|
let originalProfile: IConnectionProfile = undefined;
|
||||||
|
connectionManagementService.setup(c => c.getConnectionProfileById(TypeMoq.It.isAnyString())).returns(() => originalProfile);
|
||||||
|
const configurationService = getConfigurationServiceMock(true);
|
||||||
|
const logService = new NullLogService();
|
||||||
|
let contribution = getCommandLineContribution(connectionManagementService.object, configurationService.object, capabilitiesService, undefined, undefined, logService);
|
||||||
|
await contribution.processCommandLine(args);
|
||||||
|
connectionManagementService.verifyAll();
|
||||||
|
});
|
||||||
|
|
||||||
test('processCommandLine loads advanced options in args', async () => {
|
test('processCommandLine loads advanced options in args', async () => {
|
||||||
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
||||||
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
@@ -284,7 +316,6 @@ suite('commandLineService tests', () => {
|
|||||||
|
|
||||||
|
|
||||||
test('processCommandLine invokes a command with a profile parameter when a server is passed', async () => {
|
test('processCommandLine invokes a command with a profile parameter when a server is passed', async () => {
|
||||||
|
|
||||||
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
||||||
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,15 @@
|
|||||||
* A list of command line arguments we support natively.
|
* A list of command line arguments we support natively.
|
||||||
*/
|
*/
|
||||||
export interface NativeParsedArgs {
|
export interface NativeParsedArgs {
|
||||||
_: string[];
|
/**
|
||||||
|
* {{ SQL CARBON EDIT}} Start
|
||||||
|
* Optional for Azure Data Studio to support URI conversion.
|
||||||
|
* Used to determine file paths to be opened with SQL Editor.
|
||||||
|
* If provided, we connect the given profile to to it.
|
||||||
|
* More than one files can be passed to connect to provided profile.
|
||||||
|
*/
|
||||||
|
_?: string[];
|
||||||
|
/** {{ SQL CARBON EDIT}} End */
|
||||||
'folder-uri'?: string[]; // undefined or array of 1 or more
|
'folder-uri'?: string[]; // undefined or array of 1 or more
|
||||||
'file-uri'?: string[]; // undefined or array of 1 or more
|
'file-uri'?: string[]; // undefined or array of 1 or more
|
||||||
_urls?: string[];
|
_urls?: string[];
|
||||||
@@ -93,12 +101,55 @@ export interface NativeParsedArgs {
|
|||||||
'locate-shell-integration-path'?: string;
|
'locate-shell-integration-path'?: string;
|
||||||
|
|
||||||
// {{SQL CARBON EDIT}} Start
|
// {{SQL CARBON EDIT}} Start
|
||||||
|
/**
|
||||||
|
* Deprecated - used by SSMS - authenticationType should be used instead
|
||||||
|
*/
|
||||||
aad?: boolean;
|
aad?: boolean;
|
||||||
database?: string;
|
/**
|
||||||
integrated?: boolean;
|
* Supports providing applicationName that will be used for connection profile app name.
|
||||||
server?: string;
|
*/
|
||||||
user?: string;
|
applicationName?: string;
|
||||||
|
/**
|
||||||
|
* Provide authenticationType to be used.
|
||||||
|
* accepted values: AzureMFA, SqlLogin, Integrated, etc.
|
||||||
|
*/
|
||||||
|
authenticationType?: string
|
||||||
|
/**
|
||||||
|
* Operation to perform:
|
||||||
|
* accepted values: connect, openConnectionDialog
|
||||||
|
*/
|
||||||
command?: string;
|
command?: string;
|
||||||
|
/**
|
||||||
|
* Supports providing advanced connection properties that providers support.
|
||||||
|
* Value must be a json object containing key-value pairs in format: '{"key1":"value1","key2":"value2",...}'
|
||||||
|
*/
|
||||||
|
connectionProperties?: string;
|
||||||
|
/**
|
||||||
|
* Name of database
|
||||||
|
*/
|
||||||
|
database?: string;
|
||||||
|
/**
|
||||||
|
* Deprecated - used by SSMS - authenticationType should be used instead.
|
||||||
|
*/
|
||||||
|
integrated?: boolean;
|
||||||
|
/**
|
||||||
|
* Name of connection provider,
|
||||||
|
* accepted values: mssql (by default), pgsql, etc.
|
||||||
|
*/
|
||||||
|
provider?: string;
|
||||||
|
/**
|
||||||
|
* Name of server
|
||||||
|
*/
|
||||||
|
server?: string;
|
||||||
|
/**
|
||||||
|
* Whether or not to show dashboard
|
||||||
|
* accepted values: true, false (by default).
|
||||||
|
*/
|
||||||
|
showDashboard?: boolean;
|
||||||
|
/**
|
||||||
|
* User name/email address
|
||||||
|
*/
|
||||||
|
user?: string;
|
||||||
// {{SQL CARBON EDIT}} End
|
// {{SQL CARBON EDIT}} End
|
||||||
|
|
||||||
// chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches
|
// chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches
|
||||||
|
|||||||
@@ -131,12 +131,17 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
|
|||||||
'locate-shell-integration-path': { type: 'string', args: ['bash', 'pwsh', 'zsh'] },
|
'locate-shell-integration-path': { type: 'string', args: ['bash', 'pwsh', 'zsh'] },
|
||||||
|
|
||||||
// {{SQL CARBON EDIT}} Start
|
// {{SQL CARBON EDIT}} Start
|
||||||
'command': { type: 'string', alias: 'c', cat: 'o', args: 'command-name', description: localize('commandParameter', 'Name of command to run') },
|
'aad': { type: 'boolean', cat: 'o', description: localize('aadParameter', 'Use Azure Active Directory authentication, this option is depcrecated - use \'authenticationType\' instead.') },
|
||||||
'database': { type: 'string', alias: 'D', cat: 'o', args: 'database', description: localize('databaseParameter', 'Database name') },
|
'applicationName': { type: 'string', alias: 'A', cat: 'o', allowEmptyValue: true, description: localize('applicationNameParameter', 'Supports providing applicationName that will be used for connection profile app name.') },
|
||||||
'server': { type: 'string', alias: 'S', cat: 'o', args: 'server', description: localize('serverParameter', 'Server name') },
|
'authenticationType': { type: 'string', alias: 'T', cat: 'o', allowEmptyValue: true, deprecates: ['aad', 'integrated'], description: localize('authenticationTypeParameter', 'Provide authentication mode to be used. Accepted values: AzureMFA, SqlLogin, Integrated, etc.') },
|
||||||
'user': { type: 'string', alias: 'U', cat: 'o', args: 'user-name', description: localize('userParameter', 'User name for server connection') },
|
'command': { type: 'string', alias: 'c', cat: 'o', args: 'command-name', allowEmptyValue: true, description: localize('commandParameter', 'Name of command to run, accepted values: connect, openConnectionDialog') },
|
||||||
'aad': { type: 'boolean', cat: 'o', description: localize('aadParameter', 'Use Azure Active Directory authentication for server connection') },
|
'connectionProperties': { type: 'string', alias: 'Z', cat: 'o', allowEmptyValue: true, description: localize('connectionPropsParameter', `Supports providing advanced connection properties that providers support. Value must be a json object containing key-value pairs in format: '{"key1":"value1"}'`) },
|
||||||
'integrated': { type: 'boolean', alias: 'E', cat: 'o', description: localize('integratedAuthParameter', 'Use Integrated authentication for server connection') },
|
'database': { type: 'string', alias: 'D', cat: 'o', args: 'database', allowEmptyValue: true, description: localize('databaseParameter', 'Name of database') },
|
||||||
|
'integrated': { type: 'boolean', alias: 'E', cat: 'o', description: localize('integratedAuthParameter', 'Use Integrated authentication, this option is depcrecated - use \'authenticationType\' instead.') },
|
||||||
|
'provider': { type: 'string', alias: 'P', cat: 'o', allowEmptyValue: true, description: localize('providerParameter', 'Connection provider to use, e.g. MSSQL, PGSQL, etc. ') },
|
||||||
|
'server': { type: 'string', alias: 'S', cat: 'o', args: 'server', allowEmptyValue: true, description: localize('serverParameter', 'Name of target server or host name.') },
|
||||||
|
'showDashboard': { type: 'boolean', cat: 'o', description: localize('showDashboardParameter', 'Whether or not to show dashboard on connection, false by default.') },
|
||||||
|
'user': { type: 'string', alias: 'U', cat: 'o', args: 'user-name', allowEmptyValue: true, description: localize('userParameter', 'User name/email address') },
|
||||||
// {{SQL CARBON EDIT}} - End
|
// {{SQL CARBON EDIT}} - End
|
||||||
|
|
||||||
// chromium flags
|
// chromium flags
|
||||||
|
|||||||
Reference in New Issue
Block a user