Add getDockerImageSpec and cleanDockerObjects to API (#19900)

* Add getDockerImageSpec and cleanDockerObjects to API

* docs
This commit is contained in:
Charles Gagnon
2022-07-01 12:57:40 -07:00
committed by GitHub
parent c211fb981c
commit 60026a39f9
5 changed files with 94 additions and 49 deletions

View File

@@ -12,13 +12,8 @@ import * as vscode from 'vscode';
import { ShellExecutionHelper } from '../../tools/shellExecutionHelper';
import { AzureSqlClient } from './azureSqlClient';
import { ConnectionService } from '../connections/connectionService';
import { IDockerSettings, IPublishToDockerSettings } from 'sqldbproj';
import { DockerImageSpec, IDockerSettings, IPublishToDockerSettings } from 'sqldbproj';
interface DockerImageSpec {
label: string;
containerName: string;
tag: string
}
export class DeployService {
constructor(private _azureSqlClient = new AzureSqlClient(), private _outputChannel: vscode.OutputChannel, shellExecutionHelper: ShellExecutionHelper | undefined = undefined) {
@@ -38,28 +33,6 @@ export class DeployService {
}
}
public getDockerImageSpec(projectName: string, baseImage: string, imageUniqueId?: string): DockerImageSpec {
imageUniqueId = imageUniqueId ?? UUID.generateUuid();
// Remove unsupported characters
//
// docker image name and tag can only include letters, digits, underscore, period and dash
const regexForDockerImageName = /[^a-zA-Z0-9_,\-]/g;
let imageProjectName = projectName.replace(regexForDockerImageName, '');
const tagMaxLength = 128;
const tag = baseImage.replace(':', '-').replace(constants.sqlServerDockerRegistry, '').replace(regexForDockerImageName, '');
// cut the name if it's too long
//
imageProjectName = imageProjectName.substring(0, tagMaxLength - (constants.dockerImageNamePrefix.length + tag.length + 2));
const imageLabel = `${constants.dockerImageLabelPrefix}-${imageProjectName}`.toLocaleLowerCase();
const imageTag = `${constants.dockerImageNamePrefix}-${imageProjectName}-${tag}`.toLocaleLowerCase();
const dockerName = `${constants.dockerImageNamePrefix}-${imageProjectName}-${imageUniqueId}`.toLocaleLowerCase();
return { label: imageLabel, tag: imageTag, containerName: dockerName };
}
/**
* Creates a new Azure Sql server and tries to connect to the new server. If connection fails because of firewall rule, it prompts user to add firewall rule settings
* @param profile Azure Sql server settings
@@ -99,23 +72,14 @@ export class DeployService {
this.logToOutput(constants.dockerImageEulaMessage);
this.logToOutput(profile.dockerSettings.dockerBaseImageEula);
const imageSpec = this.getDockerImageSpec(project.projectFileName, profile.dockerSettings.dockerBaseImage);
const imageSpec = getDockerImageSpec(project.projectFileName, profile.dockerSettings.dockerBaseImage);
// If profile name is not set use the docker name to have a unique name
if (!profile.dockerSettings.profileName) {
profile.dockerSettings.profileName = imageSpec.containerName;
}
this.logToOutput(constants.cleaningDockerImagesMessage);
// Clean up existing docker image
const containerIds = await this.getCurrentDockerContainer(imageSpec.label);
if (containerIds.length > 0) {
const result = await vscode.window.showWarningMessage(constants.containerAlreadyExistForProject, constants.yesString, constants.noString);
if (result === constants.yesString) {
this.logToOutput(constants.cleaningDockerImagesMessage);
await this.cleanDockerObjects(containerIds, ['docker stop', 'docker rm']);
}
}
await this.cleanDockerObjectsIfNeeded(imageSpec.label);
this.logToOutput(constants.creatingDeploymentSettingsMessage);
// Create commands
@@ -208,6 +172,23 @@ export class DeployService {
return currentIds ? currentIds.split(/\r?\n/) : [];
}
/**
* Checks if any containers with the specified label already exist, and if they do prompt the user whether they want to clean them up
* @param imageLabel The label of the container to search for
*/
public async cleanDockerObjectsIfNeeded(imageLabel: string): Promise<void> {
this.logToOutput(constants.cleaningDockerImagesMessage);
// Clean up existing docker image
const containerIds = await this.getCurrentDockerContainer(imageLabel);
if (containerIds.length > 0) {
const result = await vscode.window.showWarningMessage(constants.containerAlreadyExistForProject, constants.yesString, constants.noString);
if (result === constants.yesString) {
this.logToOutput(constants.cleaningDockerImagesMessage);
await this.cleanDockerObjects(containerIds, ['docker stop', 'docker rm']);
}
}
}
public async cleanDockerObjects(ids: string[], commandsToClean: string[]): Promise<void> {
for (let index = 0; index < ids.length; index++) {
const id = ids[index];
@@ -220,3 +201,25 @@ export class DeployService {
}
}
}
export function getDockerImageSpec(projectName: string, baseImage: string, imageUniqueId?: string): DockerImageSpec {
imageUniqueId = imageUniqueId ?? UUID.generateUuid();
// Remove unsupported characters
//
// docker image name and tag can only include letters, digits, underscore, period and dash
const regexForDockerImageName = /[^a-zA-Z0-9_,\-]/g;
let imageProjectName = projectName.replace(regexForDockerImageName, '');
const tagMaxLength = 128;
const tag = baseImage.replace(':', '-').replace(constants.sqlServerDockerRegistry, '').replace(regexForDockerImageName, '');
// cut the name if it's too long
//
imageProjectName = imageProjectName.substring(0, tagMaxLength - (constants.dockerImageNamePrefix.length + tag.length + 2));
const imageLabel = `${constants.dockerImageLabelPrefix}-${imageProjectName}`.toLocaleLowerCase();
const imageTag = `${constants.dockerImageNamePrefix}-${imageProjectName}-${tag}`.toLocaleLowerCase();
const dockerName = `${constants.dockerImageNamePrefix}-${imageProjectName}-${imageUniqueId}`.toLocaleLowerCase();
return { label: imageLabel, tag: imageTag, containerName: dockerName };
}