mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-19 01:25:36 -05:00
SQL Database Project - Deploy db to docker (#16406)
Added a new command to deploy the project to docker
This commit is contained in:
@@ -126,6 +126,53 @@ export const selectDatabase = localize('selectDatabase', "Select database");
|
||||
export const done = localize('done', "Done");
|
||||
export const nameMustNotBeEmpty = localize('nameMustNotBeEmpty', "Name must not be empty");
|
||||
|
||||
// Deploy
|
||||
export const selectDeployOption = localize('selectDeployOption', "Select where to deploy the project to");
|
||||
export const deployToExistingServer = localize('deployToExistingServer', "Deploy to existing server");
|
||||
export const deployToDockerContainer = localize('deployToDockerContainer', "Deploy to docker container");
|
||||
export const enterPortNumber = localize('enterPortNumber', "Enter port number or press enter to use the default value");
|
||||
export const enterConnectionStringEnvName = localize('enterConnectionStringEnvName', "Enter connection string environment variable name");
|
||||
export const enterConnectionStringTemplate = localize('enterConnectionStringTemplate', "Enter connection string template");
|
||||
export const enterPassword = localize('enterPassword', "Enter password or press enter to use the generated password");
|
||||
export const portMustBeNumber = localize('portMustNotBeNumber', "Port must a be number");
|
||||
export const valueCannotBeEmpty = localize('valueCannotBeEmpty', "Value cannot be empty");
|
||||
export const dockerImageLabelPrefix = 'source=sqldbproject';
|
||||
export const dockerImageNamePrefix = 'sqldbproject';
|
||||
export const connectionNamePrefix = 'SQLDbProject';
|
||||
export const dockerBaseImage = 'mcr.microsoft.com/azure-sql-edge:latest';
|
||||
export const commandsFolderName = 'commands';
|
||||
export const mssqlFolderName = '.mssql';
|
||||
export const dockerFileName = 'Dockerfile';
|
||||
export const startCommandName = 'start.sh';
|
||||
export const defaultPortNumber = '1433';
|
||||
export const defaultConnectionStringEnvVarName = 'SQLConnectionString';
|
||||
export const defaultConnectionStringTemplate = 'Data Source=@@SERVER@@,@@PORT@@;Initial Catalog=@@DATABASE@@;User id=@@USER@@;Password=@@SA_PASSWORD@@;';
|
||||
export const azureFunctionLocalSettingsFileName = 'local.settings.json';
|
||||
export const enterConnStringTemplateDescription = localize('enterConnStringTemplateDescription', "Enter a template for SQL connection string");
|
||||
export const appSettingPrompt = localize('appSettingPrompt', "Would you like to update Azure Function local.settings.json with the new connection string?");
|
||||
export const enterConnectionStringEnvNameDescription = localize('enterConnectionStringEnvNameDescription', "Enter environment variable for SQL connection string");
|
||||
export const deployDbTaskName = localize('deployDbTaskName', "Deploying SQL Db Project Locally");
|
||||
export const deployProjectSucceed = localize('deployProjectSucceed', "Database project deployed successfully");
|
||||
export const cleaningDockerImagesMessage = localize('cleaningDockerImagesMessage', "Cleaning existing deployments...");
|
||||
export const creatingDeploymentSettingsMessage = localize('creatingDeploymentSettingsMessage', "Creating deployment settings ...");
|
||||
export const runningDockerMessage = localize('runningDockerMessage', "Building and running the docker container ...");
|
||||
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 deployProjectFailedMessage = localize('deployProjectFailedMessage', "Failed to open a connection to the deployed database'");
|
||||
export function taskFailedError(taskName: string, err: string): string { return localize('taskFailedError.error', "Failed to complete task '{0}'. Error: {1}", taskName, err); }
|
||||
export function deployProjectFailed(errorMessage: string) { return localize('deployProjectFailed', "Failed to deploy project. Check output pane for more details. {0}", errorMessage); }
|
||||
export function deployAppSettingUpdateFailed(appSetting: string) { return localize('deployAppSettingUpdateFailed', "Failed to update app setting '{0}'", appSetting); }
|
||||
export function deployAppSettingUpdating(appSetting: string) { return localize('deployAppSettingUpdating', "Updating app setting: '{0}'", appSetting); }
|
||||
export function connectionFailedError(error: string) { return localize('connectionFailedError', "Connection failed error: '{0}'", error); }
|
||||
export function dockerContainerCreatedMessage(id: string) { return localize('dockerContainerCreatedMessage', "Docker created id: '{0}'", id); }
|
||||
export function dockerLogMessage(log: string) { return localize('dockerLogMessage', "Docker logs: '{0}'", log); }
|
||||
export function retryWaitMessage(numberOfSeconds: number, name: string) { return localize('retryWaitMessage', "Waiting for {0} seconds before another attempt for operation '{1}'", numberOfSeconds, name); }
|
||||
export function retryRunMessage(attemptNumber: number, numberOfAttempts: number, name: string) { return localize('retryRunMessage', "Running operation '{2}' Attempt {0} of {1}", attemptNumber, numberOfAttempts, name); }
|
||||
export function retrySucceedMessage(name: string, result: string) { return localize('retrySucceedMessage', "Operation '{0}' completed successfully. Result: {1}", name, result); }
|
||||
export function retryFailedMessage(name: string, result: string, error: string) { return localize('retryFailedMessage', "Operation '{0}' failed. Re-trying... Current Result: {1}. Error: '{2}'", name, result, error); }
|
||||
export function retryMessage(name: string, error: string) { return localize('retryMessage', "Operation '{0}' failed. Re-trying... Error: '{1}'", name, error || ''); }
|
||||
|
||||
// Add Database Reference dialog strings
|
||||
|
||||
export const addDatabaseReferenceDialogName = localize('addDatabaseReferencedialogName', "Add database reference");
|
||||
|
||||
@@ -14,6 +14,13 @@ import * as mssql from '../../../mssql';
|
||||
import * as vscodeMssql from 'vscode-mssql';
|
||||
import { promises as fs } from 'fs';
|
||||
import { Project } from '../models/project';
|
||||
import * as childProcess from 'child_process';
|
||||
import * as fse from 'fs-extra';
|
||||
|
||||
export interface ValidationResult {
|
||||
errorMessage: string;
|
||||
validated: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Consolidates on the error message string
|
||||
@@ -395,3 +402,79 @@ try {
|
||||
export function getAzdataApi(): typeof azdataType | undefined {
|
||||
return azdataApi;
|
||||
}
|
||||
|
||||
export async function createFolderIfNotExist(folderPath: string): Promise<void> {
|
||||
try {
|
||||
await fse.mkdir(folderPath);
|
||||
} catch {
|
||||
// Ignore if failed
|
||||
}
|
||||
}
|
||||
|
||||
export async function executeCommand(cmd: string, outputChannel: vscode.OutputChannel, timeout: number = 5 * 60 * 1000): Promise<string> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
if (outputChannel) {
|
||||
outputChannel.appendLine(` > ${cmd}`);
|
||||
}
|
||||
let child = childProcess.exec(cmd, {
|
||||
timeout: timeout
|
||||
}, (err, stdout) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
|
||||
// Add listeners to print stdout and stderr if an output channel was provided
|
||||
|
||||
if (child?.stdout) {
|
||||
child.stdout.on('data', data => { outputDataChunk(outputChannel, data, ' stdout: '); });
|
||||
}
|
||||
if (child?.stderr) {
|
||||
child.stderr.on('data', data => { outputDataChunk(outputChannel, data, ' stderr: '); });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function outputDataChunk(outputChannel: vscode.OutputChannel, data: string | Buffer, header: string): void {
|
||||
data.toString().split(/\r?\n/)
|
||||
.forEach(line => {
|
||||
if (outputChannel) {
|
||||
outputChannel.appendLine(header + line);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function retry<T>(
|
||||
name: string,
|
||||
attempt: () => Promise<T>,
|
||||
verify: (result: T) => Promise<ValidationResult>,
|
||||
formatResult: (result: T) => Promise<string>,
|
||||
outputChannel: vscode.OutputChannel,
|
||||
numberOfAttempts: number = 10,
|
||||
waitInSeconds: number = 2
|
||||
): Promise<T | undefined> {
|
||||
for (let count = 0; count < numberOfAttempts; count++) {
|
||||
outputChannel.appendLine(constants.retryWaitMessage(waitInSeconds, name));
|
||||
await new Promise(c => setTimeout(c, waitInSeconds * 1000));
|
||||
outputChannel.appendLine(constants.retryRunMessage(count, numberOfAttempts, name));
|
||||
|
||||
try {
|
||||
let result = await attempt();
|
||||
const validationResult = await verify(result);
|
||||
const formattedResult = await formatResult(result);
|
||||
if (validationResult.validated) {
|
||||
outputChannel.appendLine(constants.retrySucceedMessage(name, formattedResult));
|
||||
return result;
|
||||
} else {
|
||||
outputChannel.appendLine(constants.retryFailedMessage(name, formattedResult, validationResult.errorMessage));
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
outputChannel.appendLine(constants.retryMessage(name, err));
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user