/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { SqlTargetPlatform } from 'sqldbproj'; import * as constants from '../common/constants'; import * as utils from '../common/utils'; import * as mssql from 'mssql'; import { HttpClient } from '../common/httpClient'; import { AgreementInfo, DockerImageInfo } from '../models/deploy/deployProfile'; import { IUserDatabaseReferenceSettings } from '../models/IDatabaseReferenceSettings'; import { removeSqlCmdVariableFormatting } from '../common/utils'; /** * Gets connection name from connection object if there is one, * otherwise set connection name in format that shows in OE */ export function getConnectionName(connection: any): string { let connectionName: string; if (connection.options['connectionName']) { connectionName = connection.options['connectionName']; } else { let user = connection.options['user']; if (!user) { user = constants.defaultUser; } connectionName = `${connection.options['server']} (${user})`; } return connectionName; } export function getAgreementDisplayText(agreementInfo: AgreementInfo): string { return constants.eulaAgreementText(agreementInfo.link!.text); } /** * Returns the title for SQL server based on the target version */ export function getPublishServerName(target: string): string { return target === constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlAzure) ? constants.AzureSqlServerName : constants.SqlServerName; } /** * Returns the docker image place holder based on the target version */ export function getDockerImagePlaceHolder(target: string): string { return target === constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlAzure) ? constants.dockerImagesPlaceHolder(constants.AzureSqlDbLiteDockerImageName) : constants.dockerImagesPlaceHolder(SqlTargetPlatform.sqlEdge); } /** * Returns the list of image tags for given target * @param imageInfo docker image info * @param target project target version * @param defaultTagFirst whether the default tag should be the first entry in the array * @returns image tags */ export async function getImageTags(imageInfo: DockerImageInfo, target: string, defaultTagFirst?: boolean): Promise { let imageTags: string[] | undefined = []; const versionToImageTags: Map = new Map(); try { const imageTagsFromUrl = await HttpClient.getRequest(imageInfo?.tagsUrl, true); if (imageTagsFromUrl?.tags) { // Create a map for version and tags and find the max version in the list let defaultVersion: number = 0; let maxVersionNumber: number = defaultVersion; (imageTagsFromUrl.tags as string[]).forEach(imageTag => { const version = utils.findSqlVersionInImageName(imageTag) || defaultVersion; let tags = versionToImageTags.has(version) ? versionToImageTags.get(version) : []; tags = tags ?? []; tags = tags?.concat(imageTag); versionToImageTags.set(version, tags); maxVersionNumber = version && version > maxVersionNumber ? version : maxVersionNumber; }); // Find the version maps to the target framework and default to max version in the tags const targetVersion = utils.findSqlVersionInTargetPlatform(constants.getTargetPlatformFromVersion(target)) || maxVersionNumber; // Get the image tags with no version of the one that matches project platform versionToImageTags.forEach((tags: string[], version: number) => { if (version === defaultVersion || version >= targetVersion) { imageTags = imageTags?.concat(tags); } }); imageTags = imageTags ?? []; imageTags = imageTags.sort((a, b) => a.indexOf(constants.dockerImageDefaultTag) > 0 ? -1 : a.localeCompare(b)); if (defaultTagFirst) { const defaultIndex = imageTags.findIndex(i => i === imageInfo.defaultTag); if (defaultIndex > -1) { imageTags.splice(defaultIndex, 1); imageTags.unshift(imageInfo.defaultTag); } } } } catch (err) { // Ignore the error. If http request fails, we just use the default tag console.debug(`Failed to get docker image tags ${err}`); } return imageTags; } /** * Returns the list of base images for given target version * @param target * @returns list of image info */ export function getDockerBaseImages(target: string): DockerImageInfo[] { if (target === constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlAzure)) { return [{ name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}`, displayName: constants.AzureSqlDbFullDockerImageName, agreementInfo: { link: { text: constants.eulaAgreementTitle, url: constants.sqlServerEulaLink, } }, tagsUrl: `https://${constants.sqlServerDockerRegistry}/v2/${constants.sqlServerDockerRepository}/tags/list`, defaultTag: constants.dockerImageDefaultTag }, { name: `${constants.sqlServerDockerRegistry}/${constants.azureSqlEdgeDockerRepository}`, displayName: constants.AzureSqlDbLiteDockerImageName, agreementInfo: { link: { text: constants.edgeEulaAgreementTitle, url: constants.sqlServerEdgeEulaLink, } }, tagsUrl: `https://${constants.sqlServerDockerRegistry}/v2/${constants.azureSqlEdgeDockerRepository}/tags/list`, defaultTag: constants.dockerImageDefaultTag }]; } else { return [ { name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}`, displayName: constants.SqlServerDockerImageName, agreementInfo: { link: { text: constants.eulaAgreementTitle, url: constants.sqlServerEulaLink, } }, tagsUrl: `https://${constants.sqlServerDockerRegistry}/v2/${constants.sqlServerDockerRepository}/tags/list`, defaultTag: constants.dockerImageDefaultTag }, { name: `${constants.sqlServerDockerRegistry}/${constants.azureSqlEdgeDockerRepository}`, displayName: SqlTargetPlatform.sqlEdge, agreementInfo: { link: { text: constants.edgeEulaAgreementTitle, url: constants.sqlServerEdgeEulaLink, } }, tagsUrl: `https://${constants.sqlServerDockerRegistry}/v2/${constants.azureSqlEdgeDockerRepository}/tags/list`, defaultTag: constants.dockerImageDefaultTag }, ]; } } /** * This adds the tag matching the target platform to make sure the correct image is used for the project's target platform when the docker base image is SQL Server. * If the image is Edge, then no tag is appended * @param projectTargetVersion target version of the project * @param dockerImage selected base docker image without tag * @param imageInfo docker image info of the selected docker image * @returns dockerBaseImage with the appropriate image tag appended if there is one */ export function getDefaultDockerImageWithTag(projectTargetVersion: string, dockerImage: string, imageInfo?: DockerImageInfo,): string { if (imageInfo?.displayName === constants.SqlServerDockerImageName) { switch (projectTargetVersion) { case constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlServer2022): dockerImage = `${dockerImage}:2022-latest`; break; case constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlServer2019): dockerImage = `${dockerImage}:2019-latest`; break; case constants.targetPlatformToVersion.get(SqlTargetPlatform.sqlServer2017): dockerImage = `${dockerImage}:2017-latest`; break; default: // nothing - let it be the default image defined as default in the container registry break; } } return dockerImage; } /** * Function to map folder structure string to enum * @param inputTarget folder structure in string * @returns folder structure in enum format */ export function mapExtractTargetEnum(inputTarget: string): mssql.ExtractTarget { if (inputTarget) { switch (inputTarget) { case constants.file: return mssql.ExtractTarget.file; case constants.flat: return mssql.ExtractTarget.flat; case constants.objectType: return mssql.ExtractTarget.objectType; case constants.schema: return mssql.ExtractTarget.schema; case constants.schemaObjectType: return mssql.ExtractTarget.schemaObjectType; default: throw new Error(constants.invalidInput(inputTarget)); } } else { throw new Error(constants.extractTargetRequired); } } export interface DbServerValues { dbName?: string, dbVariable?: string, serverName?: string, serverVariable?: string } export function populateResultWithVars(referenceSettings: IUserDatabaseReferenceSettings, dbServerValues: DbServerValues) { if (dbServerValues.dbVariable) { referenceSettings.databaseName = ensureSetOrDefined(dbServerValues.dbName); referenceSettings.databaseVariable = ensureSetOrDefined(removeSqlCmdVariableFormatting(dbServerValues.dbVariable)); referenceSettings.serverName = ensureSetOrDefined(dbServerValues.serverName); referenceSettings.serverVariable = ensureSetOrDefined(removeSqlCmdVariableFormatting(dbServerValues.serverVariable)); } else { referenceSettings.databaseVariableLiteralValue = ensureSetOrDefined(dbServerValues.dbName); } } /** * Returns undefined for settings that are an empty string, meaning they are unset * @param setting */ export function ensureSetOrDefined(setting?: string): string | undefined { if (!setting || setting.trim().length === 0) { return undefined; } return setting; }