mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 01:25:37 -05:00
Load connection from publish profile (#11263)
* initial changes for reading connection from profile * connection string can now be read from publish.xml * fix build errors and update test * move publish profile tests to their own file * cleanup * update message * fix string * remove apiWrapper
This commit is contained in:
@@ -15,9 +15,3 @@ export interface IGenerateScriptSettings {
|
||||
connectionUri: string;
|
||||
sqlCmdVariables?: Record<string, string>;
|
||||
}
|
||||
|
||||
// only reading db name and SQLCMD vars from profile for now
|
||||
export interface PublishProfile {
|
||||
databaseName: string;
|
||||
sqlCmdVariables: Record<string, string>;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import { DataSource } from './dataSources';
|
||||
import * as constants from '../../common/constants';
|
||||
|
||||
@@ -70,6 +71,24 @@ export class SqlConnectionDataSource extends DataSource {
|
||||
public static fromJson(json: DataSourceJson): SqlConnectionDataSource {
|
||||
return new SqlConnectionDataSource(json.name, (json.data as unknown as SqlConnectionDataSourceJson).connectionString);
|
||||
}
|
||||
|
||||
public getConnectionProfile(): azdata.IConnectionProfile {
|
||||
const connProfile: azdata.IConnectionProfile = {
|
||||
serverName: this.server,
|
||||
databaseName: this.database,
|
||||
connectionName: this.name,
|
||||
userName: this.username,
|
||||
password: this.password,
|
||||
authenticationType: this.integratedSecurity ? 'Integrated' : 'SqlAuth',
|
||||
savePassword: false,
|
||||
providerName: 'MSSQL',
|
||||
saveProfile: true,
|
||||
id: this.name + '-dataSource',
|
||||
options: []
|
||||
};
|
||||
|
||||
return connProfile;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,7 @@ import * as os from 'os';
|
||||
import { Uri } from 'vscode';
|
||||
import { promises as fs } from 'fs';
|
||||
import { DataSource } from './dataSources/dataSources';
|
||||
import { readSqlCmdVariables } from './publishProfile/publishProfile';
|
||||
|
||||
/**
|
||||
* Class representing a Project, and providing functions for operating on it
|
||||
@@ -80,7 +81,7 @@ export class Project {
|
||||
}
|
||||
|
||||
// find all SQLCMD variables to include
|
||||
this.sqlCmdVariables = utils.readSqlCmdVariables(this.projFileXmlDoc);
|
||||
this.sqlCmdVariables = readSqlCmdVariables(this.projFileXmlDoc);
|
||||
|
||||
// find all database references to include
|
||||
const references = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ArtifactReference);
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as xmldom from 'xmldom';
|
||||
import * as constants from '../../common/constants';
|
||||
import * as utils from '../../common/utils';
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
import { Uri } from 'vscode';
|
||||
import { SqlConnectionDataSource } from '../dataSources/sqlConnectionStringSource';
|
||||
|
||||
// only reading db name, connection string, and SQLCMD vars from profile for now
|
||||
export interface PublishProfile {
|
||||
databaseName: string;
|
||||
connectionId: string;
|
||||
connectionString: string;
|
||||
sqlCmdVariables: Record<string, string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* parses the specified file to load publish settings
|
||||
*/
|
||||
export async function load(profileUri: Uri): Promise<PublishProfile> {
|
||||
const profileText = await fs.readFile(profileUri.fsPath);
|
||||
const profileXmlDoc = new xmldom.DOMParser().parseFromString(profileText.toString());
|
||||
|
||||
// read target database name
|
||||
let targetDbName: string = '';
|
||||
let targetDatabaseNameCount = profileXmlDoc.documentElement.getElementsByTagName(constants.targetDatabaseName).length;
|
||||
if (targetDatabaseNameCount > 0) {
|
||||
// if there is more than one TargetDatabaseName nodes, SSDT uses the name in the last one so we'll do the same here
|
||||
targetDbName = profileXmlDoc.documentElement.getElementsByTagName(constants.targetDatabaseName)[targetDatabaseNameCount - 1].textContent;
|
||||
}
|
||||
|
||||
const connectionInfo = await readConnectionString(profileXmlDoc);
|
||||
|
||||
// get all SQLCMD variables to include from the profile
|
||||
const sqlCmdVariables = readSqlCmdVariables(profileXmlDoc);
|
||||
|
||||
return {
|
||||
databaseName: targetDbName,
|
||||
connectionId: connectionInfo.connectionId,
|
||||
connectionString: connectionInfo.connectionString,
|
||||
sqlCmdVariables: sqlCmdVariables
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Read SQLCMD variables from xmlDoc and return them
|
||||
* @param xmlDoc xml doc to read SQLCMD variables from. Format must be the same that sqlproj and publish profiles use
|
||||
*/
|
||||
export function readSqlCmdVariables(xmlDoc: any): Record<string, string> {
|
||||
let sqlCmdVariables: Record<string, string> = {};
|
||||
for (let i = 0; i < xmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable).length; i++) {
|
||||
const sqlCmdVar = xmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable)[i];
|
||||
const varName = sqlCmdVar.getAttribute(constants.Include);
|
||||
|
||||
const varValue = sqlCmdVar.getElementsByTagName(constants.DefaultValue)[0].childNodes[0].nodeValue;
|
||||
sqlCmdVariables[varName] = varValue;
|
||||
}
|
||||
|
||||
return sqlCmdVariables;
|
||||
}
|
||||
|
||||
async function readConnectionString(xmlDoc: any): Promise<{ connectionId: string, connectionString: string }> {
|
||||
let targetConnectionString: string = '';
|
||||
let connId: string = '';
|
||||
|
||||
if (xmlDoc.documentElement.getElementsByTagName('TargetConnectionString').length > 0) {
|
||||
targetConnectionString = xmlDoc.documentElement.getElementsByTagName('TargetConnectionString')[0].textContent;
|
||||
const dataSource = new SqlConnectionDataSource('temp', targetConnectionString);
|
||||
const connectionProfile = dataSource.getConnectionProfile();
|
||||
|
||||
try {
|
||||
if (dataSource.integratedSecurity) {
|
||||
connId = (await azdata.connection.connect(connectionProfile, false, false)).connectionId;
|
||||
}
|
||||
else {
|
||||
connId = (await azdata.connection.openConnectionDialog(undefined, connectionProfile)).connectionId;
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(constants.unableToCreatePublishConnection(utils.getErrorMessage(err)));
|
||||
}
|
||||
}
|
||||
|
||||
// mask password in connection string
|
||||
targetConnectionString = await azdata.connection.getConnectionString(connId, false);
|
||||
|
||||
return {
|
||||
connectionId: connId,
|
||||
connectionString: targetConnectionString
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user