Sql Proj: Adding a new sqlproj template for SQL dbs (#18636)

This commit is contained in:
Leila Lali
2022-03-29 09:06:56 -07:00
committed by GitHub
parent 25b8137a45
commit 459fab256e
28 changed files with 223 additions and 62 deletions

View File

@@ -35,7 +35,7 @@ export const DefaultInputWidth = '400px';
export const DefaultButtonWidth = '80px'; export const DefaultButtonWidth = '80px';
// New Project Dialog // New Project Dialog
export const NewProjectDialogTitle = localize('dataworkspace.NewProjectDialogTitle', "Create new project"); export const NewProjectDialogTitle = localize('dataworkspace.NewProjectDialogTitle', "Create new database project");
export const TypeTitle = localize('dataworkspace.Type', "Type"); export const TypeTitle = localize('dataworkspace.Type', "Type");
export const ProjectNameTitle = localize('dataworkspace.projectNameTitle', "Name"); export const ProjectNameTitle = localize('dataworkspace.projectNameTitle', "Name");
export const ProjectNamePlaceholder = localize('dataworkspace.projectNamePlaceholder', "Enter project name"); export const ProjectNamePlaceholder = localize('dataworkspace.projectNamePlaceholder', "Enter project name");
@@ -45,7 +45,7 @@ export const ProjectLocationPlaceholder = localize('dataworkspace.projectLocatio
export const ProjectParentDirectoryNotExistError = (location: string): string => { return localize('dataworkspace.projectParentDirectoryNotExistError', "The selected project location '{0}' does not exist or is not a directory.", location); }; export const ProjectParentDirectoryNotExistError = (location: string): string => { return localize('dataworkspace.projectParentDirectoryNotExistError', "The selected project location '{0}' does not exist or is not a directory.", location); };
export const ProjectDirectoryAlreadyExistError = (projectName: string, location: string): string => { return localize('dataworkspace.projectDirectoryAlreadyExistError', "There is already a directory named '{0}' in the selected location: '{1}'.", projectName, location); }; export const ProjectDirectoryAlreadyExistError = (projectName: string, location: string): string => { return localize('dataworkspace.projectDirectoryAlreadyExistError', "There is already a directory named '{0}' in the selected location: '{1}'.", projectName, location); };
export const ProjectDirectoryAlreadyExistErrorShort = (projectName: string) => { return localize('dataworkspace.projectDirectoryAlreadyExistErrorShort', "Directory '{0}' already exists in the selected location, please choose another", projectName); }; export const ProjectDirectoryAlreadyExistErrorShort = (projectName: string) => { return localize('dataworkspace.projectDirectoryAlreadyExistErrorShort', "Directory '{0}' already exists in the selected location, please choose another", projectName); };
export const SelectProjectType = localize('dataworkspace.selectProjectType', "Select Project Type"); export const SelectProjectType = localize('dataworkspace.selectProjectType', "Select Database Project Type");
export const SelectProjectLocation = localize('dataworkspace.selectProjectLocation', "Select Project Location"); export const SelectProjectLocation = localize('dataworkspace.selectProjectLocation', "Select Project Location");
export const NameCannotBeEmpty = localize('dataworkspace.nameCannotBeEmpty', "Name cannot be empty"); export const NameCannotBeEmpty = localize('dataworkspace.nameCannotBeEmpty', "Name cannot be empty");
export const TargetPlatform = localize('dataworkspace.targetPlatform', "Target Platform"); export const TargetPlatform = localize('dataworkspace.targetPlatform', "Target Platform");

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="28" width="28" version="1.1" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="#0072C6" d="M11.423,44.326l23.623-4.156L22.894,25.748l6.328-17.346L50,44.33L11.423,44.326z M27.566,5.67L11.469,40.109v-0.034H0l12.717-21.975L27.566,5.67z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 331 B

View File

@@ -0,0 +1,64 @@
# Welcome to Azure SQL Database Local Development experience!
## Overview
Microsoft Azure SQL Database Local Development experience for Azure Data Studio and VS Code provides a way to design, edit, build/validate, publish and run schemas for Azure SQL databases from a source-controlled project to one or more offline database instances, running in a containerized environment that offers closest fidelity with what Azure SQL Database public service. Once development gets to a more mature stage, developers can easily publish the same project to public service from the same environment, and manage the entire lifecycle of their databases (e.g. manage schema drifts and such).
## VS Code
Microsoft SQL Server Database Projects for Azure Data Studio and VS Code provides a way to design, edit, and publish and run schemas for Azure SQL databases from a source-controlled project.
## Getting Started with Database Projects
• Create a new database project by going to the Projects viewlet or by searching Projects: New in the command palette.
• Existing database projects can be opened by going to the Projects viewlet or by searching Projects: Open Existing in the command palette.
• Start from an existing database by using the Create Project from Database from the command palette or database context menu.
• Start from an OpenAPI/Swagger spec by using the Generate SQL Project from OpenAPI/Swagger spec command.
![Pic1](./assets/pic1.jpg)
Provide a name for the new database project:
![Pic2](./assets/pic2.jpg)
Start working on your project, adding database objects like tables, views, stored procedures and such:
![Pic3](./assets/pic3.jpg)
Database project files can be put under source control together with your application projects:
![Pic4](./assets/pic4.jpg)
You can get edit and build time support for your database project objects and scripts by selecting a proper target platform for your project. This will let VS Code to highlight syntax issues or the usage of unsupported features for the selected platform:
![Pic5](./assets/pic5.jpg)
You can build your project and validate that it will work against the selected platform:
![Pic6](./assets/pic6.jpg)
Once database project is ready to get tested, you can publish it to a target:
![Pic7](./assets/pic7.jpg)
You can select between an existing or a new server:
![Pic8](./assets/pic8.jpg)
And you select between Azure SQL Database “lite” and a “full” images. With the former, you will get compatibility with most of Azure SQL DB capabilities and a lightweight image that will take less to download and instantiate. Selecting “full”, you will have access to advanced features like In-memory optimized tables, geo-spatial data types and more, but at the expense of more required resources:
![Pic9](./assets/pic9.jpg)
You can create as many local instances as necessary, based on available resources, and manage their lifecycle through VS Code Docker Extension or CLI commands.
![Pic10](./assets/pic10.jpg)
Once instances of your database projects are running, you can connect from VS Code mssql extension and test your scripts and queries, like any regular Azure SQL Database instance in the cloud:
![Pic11](./assets/pic11.jpg)
For each iteration and modification, SQL project can be rebuilt and deployed to one of the containerized instances running on the local machine, until its ready.
![Pic12](./assets/pic12.jpg)
Last step of database project lifecycle can be to publish the finished artifact to a new or existing Azure SQL Database instance in the cloud through the mssql extension:
![Pic13](./assets/pic13.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -26,17 +26,21 @@ export const sqlProjectSdkVersion = '0.1.3-preview';
// Project Provider // Project Provider
export const emptySqlDatabaseProjectTypeId = 'EmptySqlDbProj'; export const emptySqlDatabaseProjectTypeId = 'EmptySqlDbProj';
export const emptyProjectTypeDisplayName = localize('emptyProjectTypeDisplayName', "SQL Database"); export const emptyProjectTypeDisplayName = localize('emptyProjectTypeDisplayName', "SQL Server Database");
export const emptyProjectTypeDescription = localize('emptyProjectTypeDescription', "Develop and publish schemas for SQL databases starting from an empty project"); export const emptyProjectTypeDescription = localize('emptyProjectTypeDescription', "Develop and publish schemas for SQL Server databases starting from an empty project");
export const edgeSqlDatabaseProjectTypeId = 'SqlDbEdgeProj'; export const edgeSqlDatabaseProjectTypeId = 'SqlDbEdgeProj';
export const edgeProjectTypeDisplayName = localize('edgeProjectTypeDisplayName', "SQL Edge"); export const edgeProjectTypeDisplayName = localize('edgeProjectTypeDisplayName', "Azure SQL Edge Database");
export const edgeProjectTypeDescription = localize('edgeProjectTypeDescription', "Start with the core pieces to develop and publish schemas for SQL Edge"); export const edgeProjectTypeDescription = localize('edgeProjectTypeDescription', "Start with the core pieces to develop and publish schemas for Azure SQL Edge Database");
export const emptySqlDatabaseSdkProjectTypeId = 'EmptySqlDbSdkProj'; export const emptySqlDatabaseSdkProjectTypeId = 'EmptySqlDbSdkProj';
export const emptySdkProjectTypeDisplayName = localize('emptySdkProjectTypeDisplayName', "SQL Database (SDK)"); export const emptySdkProjectTypeDisplayName = localize('emptySdkProjectTypeDisplayName', "SQL Database (SDK)");
export const emptySdkProjectTypeDescription = localize('emptySdkProjectTypeDescription', "Develop and publish schemas for SQL databases with Microsoft.Build.Sql (preview), starting from an empty SDK-style project."); export const emptySdkProjectTypeDescription = localize('emptySdkProjectTypeDescription', "Develop and publish schemas for SQL databases with Microsoft.Build.Sql (preview), starting from an empty SDK-style project.");
export const emptyAzureDbSqlDatabaseProjectTypeId = 'EmptyAzureSqlDbProj';
export const emptyAzureDbProjectTypeDisplayName = localize('emptyAzureDbProjectTypeDisplayName', "Azure SQL Database");
export const emptyAzureDbProjectTypeDescription = localize('emptyAzureDbProjectTypeDescription', "Develop and publish schemas for Azure SQL Database starting from an empty project");
// Dashboard // Dashboard
export const addItemAction = localize('addItemAction', "Add Item"); export const addItemAction = localize('addItemAction', "Add Item");
export const schemaCompareAction = localize('schemaCompareAction', "Schema Compare"); export const schemaCompareAction = localize('schemaCompareAction', "Schema Compare");
@@ -199,7 +203,7 @@ export const runningDockerMessage = localize('runningDockerMessage', "Running th
export function dockerNotRunningError(error: string) { return localize('dockerNotRunningError', "Failed to verify docker. Please make sure docker is installed and running. Error: '{0}'", error || ''); } export function dockerNotRunningError(error: string) { return localize('dockerNotRunningError', "Failed to verify docker. Please make sure docker is installed and running. Error: '{0}'", error || ''); }
export const dockerContainerNotRunningErrorMessage = localize('dockerContainerNotRunningErrorMessage', "Docker container is not running"); export const dockerContainerNotRunningErrorMessage = localize('dockerContainerNotRunningErrorMessage', "Docker container is not running");
export const dockerContainerFailedToRunErrorMessage = localize('dockerContainerFailedToRunErrorMessage', "Failed to run the docker container"); export const dockerContainerFailedToRunErrorMessage = localize('dockerContainerFailedToRunErrorMessage', "Failed to run the docker container");
export const connectingToSqlServerOnDockerMessage = localize('connectingToSqlServerOnDockerMessage', "Connecting to SQL Server on Docker"); export const connectingToSqlServerMessage = localize('connectingToSqlServerOnDockerMessage', "Connecting to SQL Server");
export const deployProjectFailedMessage = localize('deployProjectFailedMessage', "Failed to open a connection to the deployed database'"); export const deployProjectFailedMessage = localize('deployProjectFailedMessage', "Failed to open a connection to the deployed database'");
export const containerAlreadyExistForProject = localize('containerAlreadyExistForProject', "Containers already exist for this project. Do you want to delete them before deploying a new one?"); export const containerAlreadyExistForProject = localize('containerAlreadyExistForProject', "Containers already exist for this project. Do you want to delete them before deploying a new one?");
export const checkoutOutputMessage = localize('checkoutOutputMessage', "Check output pane for more details"); export const checkoutOutputMessage = localize('checkoutOutputMessage', "Check output pane for more details");

View File

@@ -16,6 +16,7 @@ export class IconPathHelper {
public static databaseProject: IconPath; public static databaseProject: IconPath;
public static colorfulSqlProject: IconPath; public static colorfulSqlProject: IconPath;
public static sqlEdgeProject: IconPath; public static sqlEdgeProject: IconPath;
public static azureSqlDbProject: IconPath;
public static dataSourceGroup: IconPath; public static dataSourceGroup: IconPath;
public static dataSourceSql: IconPath; public static dataSourceSql: IconPath;
@@ -48,6 +49,7 @@ export class IconPathHelper {
IconPathHelper.databaseProject = IconPathHelper.makeIcon('databaseProject'); IconPathHelper.databaseProject = IconPathHelper.makeIcon('databaseProject');
IconPathHelper.colorfulSqlProject = IconPathHelper.makeIcon('colorfulSqlProject', true); IconPathHelper.colorfulSqlProject = IconPathHelper.makeIcon('colorfulSqlProject', true);
IconPathHelper.sqlEdgeProject = IconPathHelper.makeIcon('sqlEdgeProject', true); IconPathHelper.sqlEdgeProject = IconPathHelper.makeIcon('sqlEdgeProject', true);
IconPathHelper.azureSqlDbProject = IconPathHelper.makeIcon('azure', true);
IconPathHelper.dataSourceGroup = IconPathHelper.makeIcon('dataSourceGroup'); IconPathHelper.dataSourceGroup = IconPathHelper.makeIcon('dataSourceGroup');
IconPathHelper.dataSourceSql = IconPathHelper.makeIcon('dataSource-sql'); IconPathHelper.dataSourceSql = IconPathHelper.makeIcon('dataSource-sql');

View File

@@ -8,6 +8,7 @@ import * as vscode from 'vscode';
import * as vscodeMssql from 'vscode-mssql'; import * as vscodeMssql from 'vscode-mssql';
import * as mssql from 'mssql'; import * as mssql from 'mssql';
import * as templates from '../templates/templates'; import * as templates from '../templates/templates';
import * as projectAssets from '../projectProvider/projectAssets';
import * as path from 'path'; import * as path from 'path';
import { ProjectsController } from './projectController'; import { ProjectsController } from './projectController';
@@ -88,6 +89,7 @@ export default class MainController implements vscode.Disposable {
IconPathHelper.setExtensionContext(this.extensionContext); IconPathHelper.setExtensionContext(this.extensionContext);
await templates.loadTemplates(path.join(this.context.extensionPath, 'resources', 'templates')); await templates.loadTemplates(path.join(this.context.extensionPath, 'resources', 'templates'));
projectAssets.loadAssets(path.join(this.context.extensionPath, 'resources', 'projectAssets'));
} }
public dispose(): void { public dispose(): void {

View File

@@ -11,6 +11,7 @@ import * as utils from '../common/utils';
import * as UUID from 'vscode-languageclient/lib/utils/uuid'; import * as UUID from 'vscode-languageclient/lib/utils/uuid';
import * as templates from '../templates/templates'; import * as templates from '../templates/templates';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as fse from 'fs-extra';
import type * as azdataType from 'azdata'; import type * as azdataType from 'azdata';
import * as dataworkspace from 'dataworkspace'; import * as dataworkspace from 'dataworkspace';
import type * as mssqlVscode from 'vscode-mssql'; import type * as mssqlVscode from 'vscode-mssql';
@@ -46,6 +47,7 @@ import { addDatabaseReferenceQuickpick } from '../dialogs/addDatabaseReferenceQu
import { IDeployProfile } from '../models/deploy/deployProfile'; import { IDeployProfile } from '../models/deploy/deployProfile';
import { EntryType, FileProjectEntry, IDatabaseReferenceProjectEntry, SqlProjectReferenceProjectEntry } from '../models/projectEntry'; import { EntryType, FileProjectEntry, IDatabaseReferenceProjectEntry, SqlProjectReferenceProjectEntry } from '../models/projectEntry';
import { UpdateProjectAction, UpdateProjectDataModel } from '../models/api/updateProject'; import { UpdateProjectAction, UpdateProjectDataModel } from '../models/api/updateProject';
import { targetPlatformToAssets } from '../projectProvider/projectAssets';
const maxTableLength = 10; const maxTableLength = 10;
@@ -169,10 +171,12 @@ export class ProjectsController {
throw new Error(constants.invalidTargetPlatform(creationParams.targetPlatform, Array.from(constants.targetPlatformToVersion.keys()))); throw new Error(constants.invalidTargetPlatform(creationParams.targetPlatform, Array.from(constants.targetPlatformToVersion.keys())));
} }
const targetPlatform = creationParams.targetPlatform ? constants.targetPlatformToVersion.get(creationParams.targetPlatform)! : constants.defaultDSP;
const macroDict: Record<string, string> = { const macroDict: Record<string, string> = {
'PROJECT_NAME': creationParams.newProjName, 'PROJECT_NAME': creationParams.newProjName,
'PROJECT_GUID': creationParams.projectGuid ?? UUID.generateUuid().toUpperCase(), 'PROJECT_GUID': creationParams.projectGuid ?? UUID.generateUuid().toUpperCase(),
'PROJECT_DSP': creationParams.targetPlatform ? constants.targetPlatformToVersion.get(creationParams.targetPlatform)! : constants.defaultDSP 'PROJECT_DSP': targetPlatform
}; };
let newProjFileContents = creationParams.sdkStyle ? templates.macroExpansion(templates.newSdkSqlProjectTemplate, macroDict) : templates.macroExpansion(templates.newSqlProjectTemplate, macroDict); let newProjFileContents = creationParams.sdkStyle ? templates.macroExpansion(templates.newSdkSqlProjectTemplate, macroDict) : templates.macroExpansion(templates.newSqlProjectTemplate, macroDict);
@@ -189,9 +193,24 @@ export class ProjectsController {
throw new Error(constants.projectAlreadyExists(newProjFileName, path.parse(newProjFilePath).dir)); throw new Error(constants.projectAlreadyExists(newProjFileName, path.parse(newProjFilePath).dir));
} }
await fs.mkdir(path.dirname(newProjFilePath), { recursive: true }); const projectFolderPath = path.dirname(newProjFilePath);
await fs.mkdir(projectFolderPath, { recursive: true });
await fs.writeFile(newProjFilePath, newProjFileContents); await fs.writeFile(newProjFilePath, newProjFileContents);
// Copy project readme
if (targetPlatformToAssets?.has(targetPlatform) && (targetPlatformToAssets?.get(targetPlatform)?.readmeFolder)) {
const readmeFolder = targetPlatformToAssets.get(targetPlatform)?.readmeFolder;
if (readmeFolder) {
const readmeFile = path.join(readmeFolder, 'README.md');
const folderExists = await utils.exists(readmeFile);
if (folderExists) {
await fs.copyFile(readmeFile, path.join(projectFolderPath, 'README.md'));
await fse.copy(path.join(readmeFolder, 'assets'), path.join(projectFolderPath, 'assets'));
}
}
}
await this.addTemplateFiles(newProjFilePath, creationParams.projectTypeId); await this.addTemplateFiles(newProjFilePath, creationParams.projectTypeId);
return newProjFilePath; return newProjFilePath;

View File

@@ -7,7 +7,7 @@ import * as vscode from 'vscode';
import * as constants from '../common/constants'; import * as constants from '../common/constants';
import * as utils from '../common/utils'; import * as utils from '../common/utils';
import * as uiUtils from './utils'; import * as uiUtils from './utils';
import { AppSettingType, IDeployAppIntegrationProfile, IDeployProfile, ILocalDbSetting } from '../models/deploy/deployProfile'; import { AppSettingType, DockerImageInfo, IDeployAppIntegrationProfile, IDeployProfile, ILocalDbSetting } from '../models/deploy/deployProfile';
import { Project } from '../models/project'; import { Project } from '../models/project';
import { getPublishDatabaseSettings } from './publishDatabaseQuickpick'; import { getPublishDatabaseSettings } from './publishDatabaseQuickpick';
import * as path from 'path'; import * as path from 'path';
@@ -70,10 +70,8 @@ export async function launchDeployAppIntegrationQuickpick(project: Project): Pro
}; };
} }
async function launchEulaQuickPick(baseImage: string): Promise<boolean> { async function launchEulaQuickPick(imageInfo: DockerImageInfo | undefined): Promise<boolean> {
let eulaAccepted: boolean = false; let eulaAccepted: boolean = false;
const baseImages = uiUtils.getDockerBaseImages();
const imageInfo = baseImages.find(x => x.name === baseImage);
const agreementInfo = imageInfo?.agreementInfo; const agreementInfo = imageInfo?.agreementInfo;
if (agreementInfo) { if (agreementInfo) {
const openEulaButton: vscode.QuickInputButton = { const openEulaButton: vscode.QuickInputButton = {
@@ -165,9 +163,9 @@ export async function launchPublishToDockerContainerQuickpick(project: Project):
return undefined; return undefined;
} }
const baseImages = uiUtils.getDockerBaseImages(); const baseImages = uiUtils.getDockerBaseImages(project.getProjectTargetVersion());
const baseImage = await vscode.window.showQuickPick( const baseImage = await vscode.window.showQuickPick(
baseImages.map(x => x.name), baseImages.map(x => x.displayName),
{ title: constants.selectBaseImage(name), ignoreFocusOut: true }); { title: constants.selectBaseImage(name), ignoreFocusOut: true });
// Return when user hits escape // Return when user hits escape
@@ -175,20 +173,19 @@ export async function launchPublishToDockerContainerQuickpick(project: Project):
return undefined; return undefined;
} }
const eulaAccepted = await launchEulaQuickPick(baseImage); const imageInfo = baseImages.find(x => x.displayName === baseImage);
const eulaAccepted = await launchEulaQuickPick(imageInfo);
if (!eulaAccepted) { if (!eulaAccepted) {
return undefined; return undefined;
} }
const imageInfo = baseImages.find(x => x.name === baseImage);
localDbSetting = { localDbSetting = {
serverName: constants.defaultLocalServerName, serverName: constants.defaultLocalServerName,
userName: constants.defaultLocalServerAdminName, userName: constants.defaultLocalServerAdminName,
dbName: project.projectFileName, dbName: project.projectFileName,
password: password, password: password,
port: +portNumber, port: +portNumber,
dockerBaseImage: baseImage, dockerBaseImage: imageInfo?.name || '',
dockerBaseImageEula: imageInfo?.agreementInfo?.link?.url || '' dockerBaseImageEula: imageInfo?.agreementInfo?.link?.url || ''
}; };

View File

@@ -230,7 +230,7 @@ export class PublishDatabaseDialog {
await this.publish!(this.project, settings); await this.publish!(this.project, settings);
} else { } else {
const dockerBaseImage = this.getBaseDockerImageName(); const dockerBaseImage = this.getBaseDockerImageName();
const baseImages = getDockerBaseImages(); const baseImages = getDockerBaseImages(this.project.getProjectTargetVersion());
const imageInfo = baseImages.find(x => x.name === dockerBaseImage); const imageInfo = baseImages.find(x => x.name === dockerBaseImage);
const settings: IDeployProfile = { const settings: IDeployProfile = {
localDbSetting: { localDbSetting: {
@@ -315,7 +315,7 @@ export class PublishDatabaseDialog {
} }
public getBaseDockerImageName(): string { public getBaseDockerImageName(): string {
return <string>this.baseDockerImageDropDown?.value ?? ''; return (<azdataType.CategoryValue>this.baseDockerImageDropDown?.value)?.name ?? '';
} }
public getDefaultDatabaseName(): string { public getDefaultDatabaseName(): string {
@@ -586,9 +586,10 @@ export class PublishDatabaseDialog {
}); });
const serverConfirmPasswordRow = this.createFormRow(view, constants.confirmServerPassword(name), this.serverConfigAdminPasswordTextBox); const serverConfirmPasswordRow = this.createFormRow(view, constants.confirmServerPassword(name), this.serverConfigAdminPasswordTextBox);
const baseImages = getDockerBaseImages(); const baseImages = getDockerBaseImages(this.project.getProjectTargetVersion());
const baseImagesValues: azdataType.CategoryValue[] = baseImages.map(x => { return { name: x.name, displayName: x.displayName }; });
this.baseDockerImageDropDown = view.modelBuilder.dropDown().withProps({ this.baseDockerImageDropDown = view.modelBuilder.dropDown().withProps({
values: baseImages.map(x => x.name), values: baseImagesValues,
ariaLabel: constants.baseDockerImage(name), ariaLabel: constants.baseDockerImage(name),
width: cssStyles.publishDialogTextboxWidth, width: cssStyles.publishDialogTextboxWidth,
enabled: true enabled: true
@@ -612,7 +613,7 @@ export class PublishDatabaseDialog {
if (this.eulaCheckBox) { if (this.eulaCheckBox) {
this.eulaCheckBox.checked = false; this.eulaCheckBox.checked = false;
} }
const baseImage = getDockerBaseImages().find(x => x.name === this.baseDockerImageDropDown?.value); const baseImage = getDockerBaseImages(this.project.getProjectTargetVersion()).find(x => x.name === (<azdataType.CategoryValue>this.baseDockerImageDropDown?.value).name);
if (baseImage?.agreementInfo.link) { if (baseImage?.agreementInfo.link) {
const text = view.modelBuilder.text().withProps({ const text = view.modelBuilder.text().withProps({
value: constants.eulaAgreementTemplate, value: constants.eulaAgreementTemplate,

View File

@@ -38,10 +38,32 @@ export function getPublishServerName(target: string): string {
return target === constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlAzure) ? constants.AzureSqlServerName : constants.SqlServerName; return target === constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlAzure) ? constants.AzureSqlServerName : constants.SqlServerName;
} }
export function getDockerBaseImages(): DockerImageInfo[] { export function getDockerBaseImages(target: string): DockerImageInfo[] {
if (target === constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlAzure)) {
return [{
name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2019-latest`,
displayName: SqlTargetPlatform.sqlServer2019,
agreementInfo: {
link: {
text: constants.eulaAgreementTitle,
url: constants.sqlServerEulaLink,
}
}
}, {
name: `${constants.sqlServerDockerRegistry}/${constants.azureSqlEdgeDockerRepository}:latest`,
displayName: SqlTargetPlatform.sqlEdge,
agreementInfo: {
link: {
text: constants.edgeEulaAgreementTitle,
url: constants.sqlServerEdgeEulaLink,
}
}
}];
} else {
return [ return [
{ {
name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2017-latest`, name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2017-latest`,
displayName: SqlTargetPlatform.sqlServer2017,
agreementInfo: { agreementInfo: {
link: { link: {
text: constants.eulaAgreementTitle, text: constants.eulaAgreementTitle,
@@ -51,6 +73,7 @@ export function getDockerBaseImages(): DockerImageInfo[] {
}, },
{ {
name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2019-latest`, name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2019-latest`,
displayName: SqlTargetPlatform.sqlServer2019,
agreementInfo: { agreementInfo: {
link: { link: {
text: constants.eulaAgreementTitle, text: constants.eulaAgreementTitle,
@@ -60,6 +83,7 @@ export function getDockerBaseImages(): DockerImageInfo[] {
}, },
{ {
name: `${constants.sqlServerDockerRegistry}/${constants.azureSqlEdgeDockerRepository}:latest`, name: `${constants.sqlServerDockerRegistry}/${constants.azureSqlEdgeDockerRepository}:latest`,
displayName: SqlTargetPlatform.sqlEdge,
agreementInfo: { agreementInfo: {
link: { link: {
text: constants.edgeEulaAgreementTitle, text: constants.edgeEulaAgreementTitle,
@@ -69,3 +93,4 @@ export function getDockerBaseImages(): DockerImageInfo[] {
}, },
]; ];
} }
}

View File

@@ -35,6 +35,7 @@ export interface ILocalDbSetting {
export interface DockerImageInfo { export interface DockerImageInfo {
name: string, name: string,
displayName: string,
agreementInfo: AgreementInfo agreementInfo: AgreementInfo
} }
export interface AgreementInfo { export interface AgreementInfo {

View File

@@ -310,7 +310,7 @@ export class DeployService {
public async getConnection(profile: ILocalDbSetting, saveConnectionAndPassword: boolean, database: string): Promise<string | undefined> { public async getConnection(profile: ILocalDbSetting, saveConnectionAndPassword: boolean, database: string): Promise<string | undefined> {
const getAzdataApi = await utils.getAzdataApi(); const getAzdataApi = await utils.getAzdataApi();
let connection = await utils.retry( let connection = await utils.retry(
constants.connectingToSqlServerOnDockerMessage, constants.connectingToSqlServerMessage,
async () => { async () => {
return await this.connectToDatabase(profile, saveConnectionAndPassword, database); return await this.connectToDatabase(profile, saveConnectionAndPassword, database);
}, },

View File

@@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
export interface ProjectAssets {
readmeFolder?: string
}
export let targetPlatformToAssets: Map<string, ProjectAssets>;
export function loadAssets(assetsFolderPath: string) {
targetPlatformToAssets = new Map<string, ProjectAssets>([
['AzureV12', {
readmeFolder: path.join(assetsFolderPath, 'AzureV12')
}],
]);
}

View File

@@ -35,7 +35,18 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
* Gets the supported project types * Gets the supported project types
*/ */
get supportedProjectTypes(): dataworkspace.IProjectType[] { get supportedProjectTypes(): dataworkspace.IProjectType[] {
return [{ return [
{
id: constants.emptyAzureDbSqlDatabaseProjectTypeId,
projectFileExtension: constants.sqlprojExtension.replace(/\./g, ''),
displayName: constants.emptyAzureDbProjectTypeDisplayName,
description: constants.emptyAzureDbProjectTypeDescription,
defaultTargetPlatform: sqldbproj.SqlTargetPlatform.sqlAzure,
icon: IconPathHelper.azureSqlDbProject,
sdkStyleOption: true,
sdkStyleLearnMoreUrl: constants.sdkLearnMoreUrl
},
{
id: constants.emptySqlDatabaseProjectTypeId, id: constants.emptySqlDatabaseProjectTypeId,
projectFileExtension: constants.sqlprojExtension.replace(/\./g, ''), projectFileExtension: constants.sqlprojExtension.replace(/\./g, ''),
displayName: constants.emptyProjectTypeDisplayName, displayName: constants.emptyProjectTypeDisplayName,
@@ -54,7 +65,8 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
icon: IconPathHelper.sqlEdgeProject, icon: IconPathHelper.sqlEdgeProject,
sdkStyleOption: true, sdkStyleOption: true,
sdkStyleLearnMoreUrl: constants.sdkLearnMoreUrl sdkStyleLearnMoreUrl: constants.sdkLearnMoreUrl
}]; }
];
} }
/** /**
@@ -65,6 +77,13 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
* @returns Uri of the newly created project file * @returns Uri of the newly created project file
*/ */
async createProject(name: string, location: vscode.Uri, projectTypeId: string, targetPlatform?: sqldbproj.SqlTargetPlatform, sdkStyle: boolean = true): Promise<vscode.Uri> { async createProject(name: string, location: vscode.Uri, projectTypeId: string, targetPlatform?: sqldbproj.SqlTargetPlatform, sdkStyle: boolean = true): Promise<vscode.Uri> {
if (!targetPlatform) {
const projectType = this.supportedProjectTypes.find(x => x.id === projectTypeId);
if (projectType && projectType.defaultTargetPlatform) {
targetPlatform = projectType.defaultTargetPlatform as sqldbproj.SqlTargetPlatform;
}
}
const projectFile = await this.projectController.createNewProject({ const projectFile = await this.projectController.createNewProject({
newProjName: name, newProjName: name,
folderUri: location, folderUri: location,

View File

@@ -179,6 +179,7 @@ declare module 'sqldbproj' {
sqlServer2017 = 'SQL Server 2017', sqlServer2017 = 'SQL Server 2017',
sqlServer2019 = 'SQL Server 2019', sqlServer2019 = 'SQL Server 2019',
sqlAzure = 'Microsoft Azure SQL Database', sqlAzure = 'Microsoft Azure SQL Database',
sqlDW = 'Microsoft Azure SQL Data Warehouse' sqlDW = 'Microsoft Azure SQL Data Warehouse',
sqlEdge = 'Microsoft Azure SQL Edge'
} }
} }