diff --git a/extensions/data-workspace/src/common/constants.ts b/extensions/data-workspace/src/common/constants.ts index a7829a2bad..f51a3072f6 100644 --- a/extensions/data-workspace/src/common/constants.ts +++ b/extensions/data-workspace/src/common/constants.ts @@ -35,7 +35,7 @@ export const DefaultInputWidth = '400px'; export const DefaultButtonWidth = '80px'; // 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 ProjectNameTitle = localize('dataworkspace.projectNameTitle', "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 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 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 NameCannotBeEmpty = localize('dataworkspace.nameCannotBeEmpty', "Name cannot be empty"); export const TargetPlatform = localize('dataworkspace.targetPlatform', "Target Platform"); diff --git a/extensions/sql-database-projects/images/azure.svg b/extensions/sql-database-projects/images/azure.svg new file mode 100644 index 0000000000..dd17231563 --- /dev/null +++ b/extensions/sql-database-projects/images/azure.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/README.MD b/extensions/sql-database-projects/resources/projectAssets/AzureV12/README.MD new file mode 100644 index 0000000000..31db69342d --- /dev/null +++ b/extensions/sql-database-projects/resources/projectAssets/AzureV12/README.MD @@ -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 it’s 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) diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic1.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic1.jpg new file mode 100644 index 0000000000..d073fbbd7c Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic1.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic10.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic10.jpg new file mode 100644 index 0000000000..b3c5d78c4a Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic10.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic11.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic11.jpg new file mode 100644 index 0000000000..9aed9596da Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic11.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic12.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic12.jpg new file mode 100644 index 0000000000..f51427853e Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic12.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic13.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic13.jpg new file mode 100644 index 0000000000..f187ac72f3 Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic13.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic2.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic2.jpg new file mode 100644 index 0000000000..b7bcf77dbf Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic2.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic3.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic3.jpg new file mode 100644 index 0000000000..16b75bf487 Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic3.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic4.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic4.jpg new file mode 100644 index 0000000000..2cd1e3db83 Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic4.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic5.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic5.jpg new file mode 100644 index 0000000000..8a6f65499d Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic5.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic6.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic6.jpg new file mode 100644 index 0000000000..e948900f16 Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic6.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic7.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic7.jpg new file mode 100644 index 0000000000..189858e514 Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic7.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic8.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic8.jpg new file mode 100644 index 0000000000..3db150713d Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic8.jpg differ diff --git a/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic9.jpg b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic9.jpg new file mode 100644 index 0000000000..2b9d2a883d Binary files /dev/null and b/extensions/sql-database-projects/resources/projectAssets/AzureV12/assets/pic9.jpg differ diff --git a/extensions/sql-database-projects/src/common/constants.ts b/extensions/sql-database-projects/src/common/constants.ts index d57b5ade36..ea5b2c3dfc 100644 --- a/extensions/sql-database-projects/src/common/constants.ts +++ b/extensions/sql-database-projects/src/common/constants.ts @@ -26,17 +26,21 @@ export const sqlProjectSdkVersion = '0.1.3-preview'; // Project Provider export const emptySqlDatabaseProjectTypeId = 'EmptySqlDbProj'; -export const emptyProjectTypeDisplayName = localize('emptyProjectTypeDisplayName', "SQL Database"); -export const emptyProjectTypeDescription = localize('emptyProjectTypeDescription', "Develop and publish schemas for SQL databases starting from an empty project"); +export const emptyProjectTypeDisplayName = localize('emptyProjectTypeDisplayName', "SQL Server Database"); +export const emptyProjectTypeDescription = localize('emptyProjectTypeDescription', "Develop and publish schemas for SQL Server databases starting from an empty project"); export const edgeSqlDatabaseProjectTypeId = 'SqlDbEdgeProj'; -export const edgeProjectTypeDisplayName = localize('edgeProjectTypeDisplayName', "SQL Edge"); -export const edgeProjectTypeDescription = localize('edgeProjectTypeDescription', "Start with the core pieces to develop and publish schemas for 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 Azure SQL Edge Database"); export const emptySqlDatabaseSdkProjectTypeId = 'EmptySqlDbSdkProj'; 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 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 export const addItemAction = localize('addItemAction', "Add Item"); 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 const dockerContainerNotRunningErrorMessage = localize('dockerContainerNotRunningErrorMessage', "Docker container is not running"); 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 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"); diff --git a/extensions/sql-database-projects/src/common/iconHelper.ts b/extensions/sql-database-projects/src/common/iconHelper.ts index 713f1aec59..5c32bc09d0 100644 --- a/extensions/sql-database-projects/src/common/iconHelper.ts +++ b/extensions/sql-database-projects/src/common/iconHelper.ts @@ -16,6 +16,7 @@ export class IconPathHelper { public static databaseProject: IconPath; public static colorfulSqlProject: IconPath; public static sqlEdgeProject: IconPath; + public static azureSqlDbProject: IconPath; public static dataSourceGroup: IconPath; public static dataSourceSql: IconPath; @@ -48,6 +49,7 @@ export class IconPathHelper { IconPathHelper.databaseProject = IconPathHelper.makeIcon('databaseProject'); IconPathHelper.colorfulSqlProject = IconPathHelper.makeIcon('colorfulSqlProject', true); IconPathHelper.sqlEdgeProject = IconPathHelper.makeIcon('sqlEdgeProject', true); + IconPathHelper.azureSqlDbProject = IconPathHelper.makeIcon('azure', true); IconPathHelper.dataSourceGroup = IconPathHelper.makeIcon('dataSourceGroup'); IconPathHelper.dataSourceSql = IconPathHelper.makeIcon('dataSource-sql'); diff --git a/extensions/sql-database-projects/src/controllers/mainController.ts b/extensions/sql-database-projects/src/controllers/mainController.ts index c6d4d479ae..dcbf427a74 100644 --- a/extensions/sql-database-projects/src/controllers/mainController.ts +++ b/extensions/sql-database-projects/src/controllers/mainController.ts @@ -8,6 +8,7 @@ import * as vscode from 'vscode'; import * as vscodeMssql from 'vscode-mssql'; import * as mssql from 'mssql'; import * as templates from '../templates/templates'; +import * as projectAssets from '../projectProvider/projectAssets'; import * as path from 'path'; import { ProjectsController } from './projectController'; @@ -88,6 +89,7 @@ export default class MainController implements vscode.Disposable { IconPathHelper.setExtensionContext(this.extensionContext); await templates.loadTemplates(path.join(this.context.extensionPath, 'resources', 'templates')); + projectAssets.loadAssets(path.join(this.context.extensionPath, 'resources', 'projectAssets')); } public dispose(): void { diff --git a/extensions/sql-database-projects/src/controllers/projectController.ts b/extensions/sql-database-projects/src/controllers/projectController.ts index b77d0895e2..c62cc32e99 100644 --- a/extensions/sql-database-projects/src/controllers/projectController.ts +++ b/extensions/sql-database-projects/src/controllers/projectController.ts @@ -11,6 +11,7 @@ import * as utils from '../common/utils'; import * as UUID from 'vscode-languageclient/lib/utils/uuid'; import * as templates from '../templates/templates'; import * as vscode from 'vscode'; +import * as fse from 'fs-extra'; import type * as azdataType from 'azdata'; import * as dataworkspace from 'dataworkspace'; import type * as mssqlVscode from 'vscode-mssql'; @@ -46,6 +47,7 @@ import { addDatabaseReferenceQuickpick } from '../dialogs/addDatabaseReferenceQu import { IDeployProfile } from '../models/deploy/deployProfile'; import { EntryType, FileProjectEntry, IDatabaseReferenceProjectEntry, SqlProjectReferenceProjectEntry } from '../models/projectEntry'; import { UpdateProjectAction, UpdateProjectDataModel } from '../models/api/updateProject'; +import { targetPlatformToAssets } from '../projectProvider/projectAssets'; const maxTableLength = 10; @@ -169,10 +171,12 @@ export class ProjectsController { 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 = { 'PROJECT_NAME': creationParams.newProjName, '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); @@ -189,9 +193,24 @@ export class ProjectsController { 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); + // 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); return newProjFilePath; diff --git a/extensions/sql-database-projects/src/dialogs/deployDatabaseQuickpick.ts b/extensions/sql-database-projects/src/dialogs/deployDatabaseQuickpick.ts index ba9bfcc680..b19586d1b5 100644 --- a/extensions/sql-database-projects/src/dialogs/deployDatabaseQuickpick.ts +++ b/extensions/sql-database-projects/src/dialogs/deployDatabaseQuickpick.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import * as constants from '../common/constants'; import * as utils from '../common/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 { getPublishDatabaseSettings } from './publishDatabaseQuickpick'; import * as path from 'path'; @@ -70,10 +70,8 @@ export async function launchDeployAppIntegrationQuickpick(project: Project): Pro }; } -async function launchEulaQuickPick(baseImage: string): Promise { +async function launchEulaQuickPick(imageInfo: DockerImageInfo | undefined): Promise { let eulaAccepted: boolean = false; - const baseImages = uiUtils.getDockerBaseImages(); - const imageInfo = baseImages.find(x => x.name === baseImage); const agreementInfo = imageInfo?.agreementInfo; if (agreementInfo) { const openEulaButton: vscode.QuickInputButton = { @@ -165,9 +163,9 @@ export async function launchPublishToDockerContainerQuickpick(project: Project): return undefined; } - const baseImages = uiUtils.getDockerBaseImages(); + const baseImages = uiUtils.getDockerBaseImages(project.getProjectTargetVersion()); const baseImage = await vscode.window.showQuickPick( - baseImages.map(x => x.name), + baseImages.map(x => x.displayName), { title: constants.selectBaseImage(name), ignoreFocusOut: true }); // Return when user hits escape @@ -175,20 +173,19 @@ export async function launchPublishToDockerContainerQuickpick(project: Project): return undefined; } - const eulaAccepted = await launchEulaQuickPick(baseImage); + const imageInfo = baseImages.find(x => x.displayName === baseImage); + const eulaAccepted = await launchEulaQuickPick(imageInfo); if (!eulaAccepted) { return undefined; } - const imageInfo = baseImages.find(x => x.name === baseImage); - localDbSetting = { serverName: constants.defaultLocalServerName, userName: constants.defaultLocalServerAdminName, dbName: project.projectFileName, password: password, port: +portNumber, - dockerBaseImage: baseImage, + dockerBaseImage: imageInfo?.name || '', dockerBaseImageEula: imageInfo?.agreementInfo?.link?.url || '' }; diff --git a/extensions/sql-database-projects/src/dialogs/publishDatabaseDialog.ts b/extensions/sql-database-projects/src/dialogs/publishDatabaseDialog.ts index c047340257..348abd17e2 100644 --- a/extensions/sql-database-projects/src/dialogs/publishDatabaseDialog.ts +++ b/extensions/sql-database-projects/src/dialogs/publishDatabaseDialog.ts @@ -230,7 +230,7 @@ export class PublishDatabaseDialog { await this.publish!(this.project, settings); } else { const dockerBaseImage = this.getBaseDockerImageName(); - const baseImages = getDockerBaseImages(); + const baseImages = getDockerBaseImages(this.project.getProjectTargetVersion()); const imageInfo = baseImages.find(x => x.name === dockerBaseImage); const settings: IDeployProfile = { localDbSetting: { @@ -315,7 +315,7 @@ export class PublishDatabaseDialog { } public getBaseDockerImageName(): string { - return this.baseDockerImageDropDown?.value ?? ''; + return (this.baseDockerImageDropDown?.value)?.name ?? ''; } public getDefaultDatabaseName(): string { @@ -586,9 +586,10 @@ export class PublishDatabaseDialog { }); 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({ - values: baseImages.map(x => x.name), + values: baseImagesValues, ariaLabel: constants.baseDockerImage(name), width: cssStyles.publishDialogTextboxWidth, enabled: true @@ -612,7 +613,7 @@ export class PublishDatabaseDialog { if (this.eulaCheckBox) { this.eulaCheckBox.checked = false; } - const baseImage = getDockerBaseImages().find(x => x.name === this.baseDockerImageDropDown?.value); + const baseImage = getDockerBaseImages(this.project.getProjectTargetVersion()).find(x => x.name === (this.baseDockerImageDropDown?.value).name); if (baseImage?.agreementInfo.link) { const text = view.modelBuilder.text().withProps({ value: constants.eulaAgreementTemplate, diff --git a/extensions/sql-database-projects/src/dialogs/utils.ts b/extensions/sql-database-projects/src/dialogs/utils.ts index a2e49df05b..443abd8cc7 100644 --- a/extensions/sql-database-projects/src/dialogs/utils.ts +++ b/extensions/sql-database-projects/src/dialogs/utils.ts @@ -38,34 +38,59 @@ export function getPublishServerName(target: string): string { return target === constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlAzure) ? constants.AzureSqlServerName : constants.SqlServerName; } -export function getDockerBaseImages(): DockerImageInfo[] { - return [ - { - name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2017-latest`, - agreementInfo: { - link: { - text: constants.eulaAgreementTitle, - url: constants.sqlServerEulaLink, - } - } - }, - { +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 [ + { + name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2017-latest`, + displayName: SqlTargetPlatform.sqlServer2017, + agreementInfo: { + link: { + text: constants.eulaAgreementTitle, + url: constants.sqlServerEulaLink, + } + } + }, + { + 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, + } + } + }, + ]; + } } diff --git a/extensions/sql-database-projects/src/models/deploy/deployProfile.ts b/extensions/sql-database-projects/src/models/deploy/deployProfile.ts index 2a2ee31374..1ef4d99089 100644 --- a/extensions/sql-database-projects/src/models/deploy/deployProfile.ts +++ b/extensions/sql-database-projects/src/models/deploy/deployProfile.ts @@ -35,6 +35,7 @@ export interface ILocalDbSetting { export interface DockerImageInfo { name: string, + displayName: string, agreementInfo: AgreementInfo } export interface AgreementInfo { diff --git a/extensions/sql-database-projects/src/models/deploy/deployService.ts b/extensions/sql-database-projects/src/models/deploy/deployService.ts index 6928008a46..b7da3499cc 100644 --- a/extensions/sql-database-projects/src/models/deploy/deployService.ts +++ b/extensions/sql-database-projects/src/models/deploy/deployService.ts @@ -310,7 +310,7 @@ export class DeployService { public async getConnection(profile: ILocalDbSetting, saveConnectionAndPassword: boolean, database: string): Promise { const getAzdataApi = await utils.getAzdataApi(); let connection = await utils.retry( - constants.connectingToSqlServerOnDockerMessage, + constants.connectingToSqlServerMessage, async () => { return await this.connectToDatabase(profile, saveConnectionAndPassword, database); }, diff --git a/extensions/sql-database-projects/src/projectProvider/projectAssets.ts b/extensions/sql-database-projects/src/projectProvider/projectAssets.ts new file mode 100644 index 0000000000..e7303b7747 --- /dev/null +++ b/extensions/sql-database-projects/src/projectProvider/projectAssets.ts @@ -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; + +export function loadAssets(assetsFolderPath: string) { + targetPlatformToAssets = new Map([ + ['AzureV12', { + readmeFolder: path.join(assetsFolderPath, 'AzureV12') + }], + ]); +} diff --git a/extensions/sql-database-projects/src/projectProvider/projectProvider.ts b/extensions/sql-database-projects/src/projectProvider/projectProvider.ts index 770c084be7..189cadcc3e 100644 --- a/extensions/sql-database-projects/src/projectProvider/projectProvider.ts +++ b/extensions/sql-database-projects/src/projectProvider/projectProvider.ts @@ -35,26 +35,38 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide * Gets the supported project types */ get supportedProjectTypes(): dataworkspace.IProjectType[] { - return [{ - id: constants.emptySqlDatabaseProjectTypeId, - projectFileExtension: constants.sqlprojExtension.replace(/\./g, ''), - displayName: constants.emptyProjectTypeDisplayName, - description: constants.emptyProjectTypeDescription, - icon: IconPathHelper.colorfulSqlProject, - targetPlatforms: Array.from(constants.targetPlatformToVersion.keys()), - defaultTargetPlatform: constants.defaultTargetPlatform, - sdkStyleOption: true, - sdkStyleLearnMoreUrl: constants.sdkLearnMoreUrl - }, - { - id: constants.edgeSqlDatabaseProjectTypeId, - projectFileExtension: constants.sqlprojExtension.replace(/\./g, ''), - displayName: constants.edgeProjectTypeDisplayName, - description: constants.edgeProjectTypeDescription, - icon: IconPathHelper.sqlEdgeProject, - sdkStyleOption: true, - sdkStyleLearnMoreUrl: constants.sdkLearnMoreUrl - }]; + 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, + projectFileExtension: constants.sqlprojExtension.replace(/\./g, ''), + displayName: constants.emptyProjectTypeDisplayName, + description: constants.emptyProjectTypeDescription, + icon: IconPathHelper.colorfulSqlProject, + targetPlatforms: Array.from(constants.targetPlatformToVersion.keys()), + defaultTargetPlatform: constants.defaultTargetPlatform, + sdkStyleOption: true, + sdkStyleLearnMoreUrl: constants.sdkLearnMoreUrl + }, + { + id: constants.edgeSqlDatabaseProjectTypeId, + projectFileExtension: constants.sqlprojExtension.replace(/\./g, ''), + displayName: constants.edgeProjectTypeDisplayName, + description: constants.edgeProjectTypeDescription, + icon: IconPathHelper.sqlEdgeProject, + sdkStyleOption: true, + sdkStyleLearnMoreUrl: constants.sdkLearnMoreUrl + } + ]; } /** @@ -65,6 +77,13 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide * @returns Uri of the newly created project file */ async createProject(name: string, location: vscode.Uri, projectTypeId: string, targetPlatform?: sqldbproj.SqlTargetPlatform, sdkStyle: boolean = true): Promise { + + 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({ newProjName: name, folderUri: location, diff --git a/extensions/sql-database-projects/src/sqldbproj.d.ts b/extensions/sql-database-projects/src/sqldbproj.d.ts index da5fa395d1..f70da2d78b 100644 --- a/extensions/sql-database-projects/src/sqldbproj.d.ts +++ b/extensions/sql-database-projects/src/sqldbproj.d.ts @@ -179,6 +179,7 @@ declare module 'sqldbproj' { sqlServer2017 = 'SQL Server 2017', sqlServer2019 = 'SQL Server 2019', sqlAzure = 'Microsoft Azure SQL Database', - sqlDW = 'Microsoft Azure SQL Data Warehouse' + sqlDW = 'Microsoft Azure SQL Data Warehouse', + sqlEdge = 'Microsoft Azure SQL Edge' } }