Additional SQL Proj cleanup (#19836)

This commit is contained in:
Charles Gagnon
2022-06-27 17:29:49 -07:00
committed by GitHub
parent 5dea50efa3
commit 87f8f2fd90
10 changed files with 75 additions and 66 deletions

View File

@@ -38,7 +38,7 @@ import { DashboardData, PublishData, Status } from '../models/dashboardData/dash
import { getPublishDatabaseSettings, launchPublishTargetOption } from '../dialogs/publishDatabaseQuickpick';
import { launchCreateAzureServerQuickPick, getPublishToDockerSettings } from '../dialogs/deployDatabaseQuickpick';
import { DeployService } from '../models/deploy/deployService';
import { AddItemOptions, EntryType, GenerateProjectFromOpenApiSpecOptions, IDatabaseReferenceProjectEntry, IDeploySettings, IPublishToDockerSettings, ISqlProject, ItemType, SqlTargetPlatform } from 'sqldbproj';
import { AddItemOptions, EntryType, GenerateProjectFromOpenApiSpecOptions, IDatabaseReferenceProjectEntry, ISqlProjectPublishSettings, IPublishToDockerSettings, ISqlProject, ItemType, SqlTargetPlatform } from 'sqldbproj';
import { AutorestHelper } from '../tools/autorestHelper';
import { createNewProjectFromDatabaseWithQuickpick } from '../dialogs/createProjectFromDatabaseQuickpick';
import { addDatabaseReferenceQuickpick } from '../dialogs/addDatabaseReferenceQuickpick';
@@ -320,27 +320,27 @@ export class ProjectsController {
const project: Project = this.getProjectFromContext(context);
// Removing the path separator from the image base name to be able to add that in the telemetry. With the separator the name is flagged as user path which is not true
// We only need to know the image base parts so it's ok to use a different separator when adding to telemetry
const dockerImageNameForTelemetry = deployProfile.localDbSetting?.dockerBaseImage ? deployProfile.localDbSetting.dockerBaseImage.replace(/\//gi, '_') : '';
const dockerImageNameForTelemetry = deployProfile.dockerSettings?.dockerBaseImage ? deployProfile.dockerSettings.dockerBaseImage.replace(/\//gi, '_') : '';
try {
TelemetryReporter.createActionEvent(TelemetryViews.ProjectController, TelemetryActions.publishToContainer)
.withAdditionalProperties({ dockerBaseImage: dockerImageNameForTelemetry })
.send();
if (deployProfile && deployProfile.deploySettings) {
if (deployProfile && deployProfile.sqlProjectPublishSettings) {
let connectionUri: string | undefined;
if (deployProfile.localDbSetting) {
if (deployProfile.dockerSettings) {
void utils.showInfoMessageWithOutputChannel(constants.publishingProjectMessage, this._outputChannel);
connectionUri = await this.deployService.deployToContainer(deployProfile, project);
if (connectionUri) {
deployProfile.deploySettings.connectionUri = connectionUri;
deployProfile.sqlProjectPublishSettings.connectionUri = connectionUri;
}
}
if (deployProfile.deploySettings.connectionUri) {
const publishResult = await this.publishOrScriptProject(project, deployProfile.deploySettings, true);
if (deployProfile.sqlProjectPublishSettings.connectionUri) {
const publishResult = await this.publishOrScriptProject(project, deployProfile.sqlProjectPublishSettings, true);
if (publishResult && publishResult.success) {
if (deployProfile.localDbSetting) {
await this.connectionService.getConnection(deployProfile.localDbSetting, true, deployProfile.localDbSetting.dbName);
if (deployProfile.dockerSettings) {
await this.connectionService.getConnection(deployProfile.dockerSettings, true, deployProfile.dockerSettings.dbName);
}
void vscode.window.showInformationMessage(constants.publishProjectSucceed);
} else {
@@ -400,7 +400,7 @@ export class ProjectsController {
if (publishTarget === constants.PublishTargetType.docker) {
const deployProfile = await getPublishToDockerSettings(project);
if (deployProfile?.deploySettings && deployProfile?.localDbSetting) {
if (deployProfile?.sqlProjectPublishSettings && deployProfile?.dockerSettings) {
await this.publishToDockerContainer(project, deployProfile);
}
} else if (publishTarget === constants.PublishTargetType.newAzureServer) {
@@ -414,7 +414,7 @@ export class ProjectsController {
}
} else {
let settings: IDeploySettings | undefined = await getPublishDatabaseSettings(project);
let settings: ISqlProjectPublishSettings | undefined = await getPublishDatabaseSettings(project);
if (settings) {
// 5. Select action to take
@@ -436,7 +436,7 @@ export class ProjectsController {
* @param publish Whether to publish the deployment or just generate a script
* @returns The DacFx result of the deployment
*/
public async publishOrScriptProject(project: Project, settings: IDeploySettings, publish: boolean): Promise<mssql.DacFxResult | undefined> {
public async publishOrScriptProject(project: Project, settings: ISqlProjectPublishSettings, publish: boolean): Promise<mssql.DacFxResult | undefined> {
const telemetryProps: Record<string, string> = {};
const telemetryMeasures: Record<string, number> = {};
const buildStartTime = new Date().getTime();

View File

@@ -14,7 +14,7 @@ import * as path from 'path';
import * as fse from 'fs-extra';
import { AzureSqlClient } from '../models/deploy/azureSqlClient';
import { IAccount } from 'vscode-mssql';
import { IDeploySettings, ILocalDbSetting, IPublishToDockerSettings, ISqlProject } from 'sqldbproj';
import { ISqlProjectPublishSettings, IDockerSettings, IPublishToDockerSettings, ISqlProject } from 'sqldbproj';
/**
* Create flow for Deploying a database using only VS Code-native APIs such as QuickPick
@@ -252,7 +252,7 @@ export async function launchCreateAzureServerQuickPick(project: Project, azureSq
return undefined;
}
let settings: IDeploySettings | undefined = await getPublishDatabaseSettings(project, false);
let settings: ISqlProjectPublishSettings | undefined = await getPublishDatabaseSettings(project, false);
return {
// TODO add tenant
@@ -278,7 +278,7 @@ export async function launchCreateAzureServerQuickPick(project: Project, azureSq
export async function getPublishToDockerSettings(project: ISqlProject): Promise<IPublishToDockerSettings | undefined> {
const target = project.getProjectTargetVersion();
const name = uiUtils.getPublishServerName(target);
let localDbSetting: ILocalDbSetting | undefined;
let localDbSetting: IDockerSettings | undefined;
// Deploy to docker selected
let portNumber = await vscode.window.showInputBox({
title: constants.enterPortNumber(name),
@@ -394,7 +394,7 @@ export async function getPublishToDockerSettings(project: ISqlProject): Promise<
localDbSetting.dbName = deploySettings.databaseName;
return {
localDbSetting: localDbSetting,
deploySettings: deploySettings,
dockerSettings: localDbSetting,
sqlProjectPublishSettings: deploySettings,
};
}

View File

@@ -17,7 +17,7 @@ import { getAgreementDisplayText, getConnectionName, getDockerBaseImages, getPub
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
import { Deferred } from '../common/promise';
import { PublishOptionsDialog } from './publishOptionsDialog';
import { IDeploySettings, IPublishToDockerSettings } from 'sqldbproj';
import { ISqlProjectPublishSettings, IPublishToDockerSettings } from 'sqldbproj';
interface DataSourceDropdownValue extends azdataType.CategoryValue {
dataSource: SqlConnectionDataSource;
@@ -63,9 +63,9 @@ export class PublishDatabaseDialog {
private toDispose: vscode.Disposable[] = [];
public publish: ((proj: Project, profile: IDeploySettings) => any) | undefined;
public publish: ((proj: Project, profile: ISqlProjectPublishSettings) => any) | undefined;
public publishToContainer: ((proj: Project, profile: IPublishToDockerSettings) => any) | undefined;
public generateScript: ((proj: Project, profile: IDeploySettings) => any) | undefined;
public generateScript: ((proj: Project, profile: ISqlProjectPublishSettings) => any) | undefined;
public readPublishProfile: ((profileUri: vscode.Uri) => any) | undefined;
constructor(private project: Project) {
@@ -224,7 +224,7 @@ export class PublishDatabaseDialog {
public async publishClick(): Promise<void> {
if (this.existingServerSelected) {
const settings: IDeploySettings = {
const settings: ISqlProjectPublishSettings = {
databaseName: this.targetDatabaseName,
serverName: this.getServerName(),
connectionUri: await this.getConnectionUri(),
@@ -240,7 +240,7 @@ export class PublishDatabaseDialog {
const baseImages = getDockerBaseImages(this.project.getProjectTargetVersion());
const imageInfo = baseImages.find(x => x.name === dockerBaseImage);
const settings: IPublishToDockerSettings = {
localDbSetting: {
dockerSettings: {
dbName: this.targetDatabaseName,
dockerBaseImage: dockerBaseImage,
dockerBaseImageEula: imageInfo?.agreementInfo?.link?.url || '',
@@ -249,7 +249,7 @@ export class PublishDatabaseDialog {
serverName: constants.defaultLocalServerName,
userName: constants.defaultLocalServerAdminName
},
deploySettings: {
sqlProjectPublishSettings: {
databaseName: this.targetDatabaseName,
serverName: constants.defaultLocalServerName,
connectionUri: '',
@@ -270,7 +270,7 @@ export class PublishDatabaseDialog {
TelemetryReporter.sendActionEvent(TelemetryViews.SqlProjectPublishDialog, TelemetryActions.generateScriptClicked);
const sqlCmdVars = this.getSqlCmdVariablesForPublish();
const settings: IDeploySettings = {
const settings: ISqlProjectPublishSettings = {
databaseName: this.targetDatabaseName,
serverName: this.getServerName(),
connectionUri: await this.getConnectionUri(),

View File

@@ -11,12 +11,12 @@ import { promptForPublishProfile } from './publishDatabaseDialog';
import { getDefaultPublishDeploymentOptions, getVscodeMssqlApi } from '../common/utils';
import { IConnectionInfo, IFireWallRuleError } from 'vscode-mssql';
import { getPublishServerName } from './utils';
import { IDeploySettings, ISqlProject, SqlTargetPlatform } from 'sqldbproj';
import { ISqlProjectPublishSettings, ISqlProject, SqlTargetPlatform } from 'sqldbproj';
/**
* Create flow for Publishing a database using only VS Code-native APIs such as QuickPick
*/
export async function getPublishDatabaseSettings(project: ISqlProject, promptForConnection: boolean = true): Promise<IDeploySettings | undefined> {
export async function getPublishDatabaseSettings(project: ISqlProject, promptForConnection: boolean = true): Promise<ISqlProjectPublishSettings | undefined> {
// 1. Select publish settings file (optional)
// Create custom quickpick so we can control stuff like displaying the loading indicator
@@ -207,7 +207,7 @@ export async function getPublishDatabaseSettings(project: ISqlProject, promptFor
}
// 6. Generate script/publish
let settings: IDeploySettings = {
let settings: ISqlProjectPublishSettings = {
databaseName: databaseName,
serverName: connectionProfile?.server || '',
connectionUri: connectionUri || '',

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import type * as azdataType from 'azdata';
import { IDeploySettings, ISqlConnectionProperties } from 'sqldbproj';
import { ISqlProjectPublishSettings, ISqlConnectionProperties } from 'sqldbproj';
import { IAzureAccountSession } from 'vscode-mssql';
export enum AppSettingType {
@@ -14,7 +14,7 @@ export enum AppSettingType {
export interface ISqlDbDeployProfile {
sqlDbSetting?: ISqlDbSetting;
deploySettings?: IDeploySettings;
deploySettings?: ISqlProjectPublishSettings;
}
export interface IDeployAppIntegrationProfile {

View File

@@ -12,7 +12,7 @@ import * as vscode from 'vscode';
import { ShellExecutionHelper } from '../../tools/shellExecutionHelper';
import { AzureSqlClient } from './azureSqlClient';
import { ConnectionService } from '../connections/connectionService';
import { ILocalDbSetting, IPublishToDockerSettings } from 'sqldbproj';
import { IDockerSettings, IPublishToDockerSettings } from 'sqldbproj';
interface DockerImageSpec {
label: string;
@@ -92,22 +92,22 @@ export class DeployService {
public async deployToContainer(profile: IPublishToDockerSettings, project: Project): Promise<string | undefined> {
return await this.executeTask(constants.deployDbTaskName, async () => {
if (!profile.localDbSetting) {
if (!profile.dockerSettings) {
return undefined;
}
await this.verifyDocker();
this.logToOutput(constants.dockerImageMessage);
this.logToOutput(profile.localDbSetting.dockerBaseImage);
this.logToOutput(profile.dockerSettings.dockerBaseImage);
this.logToOutput(constants.dockerImageEulaMessage);
this.logToOutput(profile.localDbSetting.dockerBaseImageEula);
this.logToOutput(profile.dockerSettings.dockerBaseImageEula);
const imageSpec = this.getDockerImageSpec(project.projectFileName, profile.localDbSetting.dockerBaseImage);
const imageSpec = this.getDockerImageSpec(project.projectFileName, profile.dockerSettings.dockerBaseImage);
// If profile name is not set use the docker name to have a unique name
if (!profile.localDbSetting.profileName) {
profile.localDbSetting.profileName = imageSpec.containerName;
if (!profile.dockerSettings.profileName) {
profile.dockerSettings.profileName = imageSpec.containerName;
}
this.logToOutput(constants.cleaningDockerImagesMessage);
@@ -128,7 +128,7 @@ export class DeployService {
this.logToOutput(constants.runningDockerMessage);
// Building the image and running the docker
//
const createdDockerId: string | undefined = await this.runDockerContainer(imageSpec, profile.localDbSetting);
const createdDockerId: string | undefined = await this.runDockerContainer(imageSpec, profile.dockerSettings);
this.logToOutput(`Docker container created. Id: ${createdDockerId}`);
@@ -145,7 +145,7 @@ export class DeployService {
if (runningDockerId) {
this.logToOutput(constants.dockerContainerCreatedMessage(runningDockerId));
return await this._connectionService.getConnection(profile.localDbSetting, false, 'master');
return await this._connectionService.getConnection(profile.dockerSettings, false, 'master');
} else {
this.logToOutput(constants.dockerContainerFailedToRunErrorMessage);
@@ -159,7 +159,7 @@ export class DeployService {
});
}
private async runDockerContainer(dockerImageSpec: DockerImageSpec, profile: ILocalDbSetting): Promise<string | undefined> {
private async runDockerContainer(dockerImageSpec: DockerImageSpec, profile: IDockerSettings): Promise<string | undefined> {
// Sensitive data to remove from output console
const sensitiveData = [profile.password];

View File

@@ -25,7 +25,7 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
* Gets the project tree data provider
* @param projectFilePath The project file Uri
*/
async getProjectTreeDataProvider(projectFilePath: vscode.Uri): Promise<vscode.TreeDataProvider<BaseProjectTreeItem>> {
public async getProjectTreeDataProvider(projectFilePath: vscode.Uri): Promise<vscode.TreeDataProvider<BaseProjectTreeItem>> {
const provider = new SqlDatabaseProjectTreeViewProvider();
const project = await Project.openProject(projectFilePath.fsPath);
provider.load([project]);
@@ -35,7 +35,7 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
/**
* Gets the supported project types
*/
get supportedProjectTypes(): dataworkspace.IProjectType[] {
public get supportedProjectTypes(): dataworkspace.IProjectType[] {
return [
{
id: constants.emptyAzureDbSqlDatabaseProjectTypeId,
@@ -80,7 +80,7 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
* @param sdkStyle whether project is sdk-style. Default is false
* @returns Uri of the newly created project file
*/
async createProject(name: string, location: vscode.Uri, projectTypeId: string, targetPlatform?: sqldbproj.SqlTargetPlatform, sdkStyle: boolean = false): Promise<vscode.Uri> {
public async createProject(name: string, location: vscode.Uri, projectTypeId: string, targetPlatform?: sqldbproj.SqlTargetPlatform, sdkStyle: boolean = false): Promise<vscode.Uri> {
if (!targetPlatform) {
const projectType = this.supportedProjectTypes.find(x => x.id === projectTypeId);
@@ -102,7 +102,7 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
/**
* Opens and loads a .sqlproj file
*/
openProject(projectFilePath: string): Promise<sqldbproj.ISqlProject> {
public openProject(projectFilePath: string): Promise<sqldbproj.ISqlProject> {
return Project.openProject(projectFilePath);
}
@@ -113,7 +113,7 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
/**
* Gets the project actions to be placed on the dashboard toolbar
*/
get projectToolbarActions(): (dataworkspace.IProjectAction | dataworkspace.IProjectActionGroup)[] {
public get projectToolbarActions(): (dataworkspace.IProjectAction | dataworkspace.IProjectActionGroup)[] {
const addItemAction: dataworkspace.IProjectAction = {
id: constants.addItemAction,
icon: IconPathHelper.add,
@@ -152,7 +152,7 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
/**
* Gets the data to be displayed in the project dashboard
*/
getDashboardComponents(projectFile: string): dataworkspace.IDashboardTable[] {
public getDashboardComponents(projectFile: string): dataworkspace.IDashboardTable[] {
const width = 200;
const publishInfo: dataworkspace.IDashboardTable = {
name: constants.PublishHistory,
@@ -177,11 +177,11 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
return [publishInfo, buildInfo];
}
get image(): ThemedIconPath {
public get image(): ThemedIconPath {
return IconPathHelper.dashboardSqlProj;
}
async openSqlNewProjectDialog(allowedTargetPlatforms?: sqldbproj.SqlTargetPlatform[]): Promise<vscode.Uri | undefined> {
public openSqlNewProjectDialog(allowedTargetPlatforms?: sqldbproj.SqlTargetPlatform[]): Promise<vscode.Uri | undefined> {
let targetPlatforms = Array.from(constants.targetPlatformToVersion.keys());
if (allowedTargetPlatforms) {
targetPlatforms = targetPlatforms.filter(p => allowedTargetPlatforms.toString().includes(p));
@@ -205,22 +205,22 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
* Gets the list of .sql scripts contained in a project
* @param projectFilePath
*/
async getProjectScriptFiles(projectFilePath: string): Promise<string[]> {
return await this.projectController.getProjectScriptFiles(projectFilePath);
public getProjectScriptFiles(projectFilePath: string): Promise<string[]> {
return this.projectController.getProjectScriptFiles(projectFilePath);
}
/**
* Gets the Database Schema Provider version for a SQL project
*/
public async getProjectDatabaseSchemaProvider(projectFilePath: string): Promise<string> {
return await this.projectController.getProjectDatabaseSchemaProvider(projectFilePath);
public getProjectDatabaseSchemaProvider(projectFilePath: string): Promise<string> {
return this.projectController.getProjectDatabaseSchemaProvider(projectFilePath);
}
public async generateProjectFromOpenApiSpec(options?: sqldbproj.GenerateProjectFromOpenApiSpecOptions): Promise<sqldbproj.ISqlProject | undefined> {
return await this.projectController.generateProjectFromOpenApiSpec(options);
public generateProjectFromOpenApiSpec(options?: sqldbproj.GenerateProjectFromOpenApiSpecOptions): Promise<sqldbproj.ISqlProject | undefined> {
return this.projectController.generateProjectFromOpenApiSpec(options);
}
getPublishToDockerSettings(project: sqldbproj.ISqlProject): Promise<sqldbproj.IPublishToDockerSettings | undefined> {
public getPublishToDockerSettings(project: sqldbproj.ISqlProject): Promise<sqldbproj.IPublishToDockerSettings | undefined> {
return getPublishToDockerSettings(project);
}
}

View File

@@ -304,19 +304,28 @@ declare module 'sqldbproj' {
connectionRetryTimeout?: number
}
export interface ILocalDbSetting extends ISqlConnectionProperties {
/**
* Settings for creating the docker container a project is being published to
*/
export interface IDockerSettings extends ISqlConnectionProperties {
dockerBaseImage: string,
dockerBaseImageEula: string,
}
/**
* Settings for publishing a SQL Project to a docker container
*/
export interface IPublishToDockerSettings {
localDbSetting?: ILocalDbSetting;
deploySettings?: IDeploySettings;
dockerSettings?: IDockerSettings;
sqlProjectPublishSettings?: ISqlProjectPublishSettings;
}
export type DeploymentOptions = mssqlDeploymentOptions | vscodeMssqlDeploymentOptions;
export interface IDeploySettings {
/**
* Settings to use when publishing a SQL Project
*/
export interface ISqlProjectPublishSettings {
databaseName: string;
serverName: string;
connectionUri: string;

View File

@@ -72,7 +72,7 @@ describe('deploy service', function (): void {
it('Should deploy a database to docker container successfully', async function (): Promise<void> {
const testContext = createContext();
const deployProfile: IPublishToDockerSettings = {
localDbSetting: {
dockerSettings: {
dbName: 'test',
password: 'PLACEHOLDER',
port: 1433,
@@ -102,7 +102,7 @@ describe('deploy service', function (): void {
it('Should fail the deploy if docker is not running', async function (): Promise<void> {
const testContext = createContext();
const deployProfile: IPublishToDockerSettings = {
localDbSetting: {
dockerSettings: {
dbName: 'test',
password: 'PLACEHOLDER',
port: 1433,

View File

@@ -17,7 +17,7 @@ import { Project } from '../../models/project';
import { ProjectsController } from '../../controllers/projectController';
import { emptySqlDatabaseProjectTypeId } from '../../common/constants';
import { createContext, mockDacFxOptionsResult, TestContext } from '../testContext';
import { IDeploySettings, IPublishToDockerSettings } from 'sqldbproj';
import { ISqlProjectPublishSettings, IPublishToDockerSettings } from 'sqldbproj';
let testContext: TestContext;
describe('Publish Database Dialog', () => {
@@ -75,9 +75,9 @@ describe('Publish Database Dialog', () => {
dialog.object.publishToExistingServer = true;
dialog.callBase = true;
let profile: IDeploySettings | undefined;
let profile: ISqlProjectPublishSettings | undefined;
const expectedPublish: IDeploySettings = {
const expectedPublish: ISqlProjectPublishSettings = {
databaseName: 'MockDatabaseName',
serverName: 'MockServer',
connectionUri: 'Mock|Connection|Uri',
@@ -94,7 +94,7 @@ describe('Publish Database Dialog', () => {
should(profile).deepEqual(expectedPublish);
const expectedGenScript: IDeploySettings = {
const expectedGenScript: ISqlProjectPublishSettings = {
databaseName: 'MockDatabaseName',
serverName: 'MockServer',
connectionUri: 'Mock|Connection|Uri',
@@ -112,7 +112,7 @@ describe('Publish Database Dialog', () => {
should(profile).deepEqual(expectedGenScript);
const expectedContainerPublishProfile: IPublishToDockerSettings = {
localDbSetting: {
dockerSettings: {
dbName: 'MockDatabaseName',
dockerBaseImage: '',
password: '',
@@ -122,7 +122,7 @@ describe('Publish Database Dialog', () => {
dockerBaseImageEula: ''
},
deploySettings: {
sqlProjectPublishSettings: {
databaseName: 'MockDatabaseName',
serverName: 'localhost',
connectionUri: '',