Added UI for user to accept EULA when deploying sql proj to docker container (#17762)

This commit is contained in:
Leila Lali
2021-11-30 15:08:23 -08:00
committed by GitHub
parent ce7935e7d2
commit 7e17bfb6ec
8 changed files with 163 additions and 17 deletions

View File

@@ -70,6 +70,50 @@ export async function launchDeployAppIntegrationQuickpick(project: Project): Pro
};
}
async function launchEulaQuickPick(baseImage: string): Promise<boolean> {
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 = {
iconPath: new vscode.ThemeIcon('link-external'),
tooltip: constants.openEulaString
};
const quickPick = vscode.window.createQuickPick();
quickPick.items = [{ label: constants.yesString },
{ label: constants.noString }];
quickPick.title = uiUtils.getAgreementDisplayText(agreementInfo);
quickPick.ignoreFocusOut = true;
quickPick.buttons = [openEulaButton];
const disposables: vscode.Disposable[] = [];
try {
const eulaAcceptedPromise = new Promise<boolean>((resolve) => {
disposables.push(
quickPick.onDidHide(() => {
resolve(false);
}),
quickPick.onDidTriggerButton(async () => {
await vscode.env.openExternal(vscode.Uri.parse(agreementInfo.link.url));
}),
quickPick.onDidChangeSelection((item) => {
resolve(item[0].label === constants.yesString);
}));
});
quickPick.show();
eulaAccepted = await eulaAcceptedPromise;
quickPick.hide();
}
finally {
disposables.forEach(d => d.dispose());
}
return eulaAccepted;
}
return false;
}
/**
* Create flow for publishing a database to docker container using only VS Code-native APIs such as QuickPick
*/
@@ -120,8 +164,9 @@ export async function launchPublishToDockerContainerQuickpick(project: Project):
return undefined;
}
const baseImages = uiUtils.getDockerBaseImages();
const baseImage = await vscode.window.showQuickPick(
uiUtils.getDockerBaseImages(),
baseImages.map(x => x.name),
{ title: constants.selectBaseImage, ignoreFocusOut: true });
// Return when user hits escape
@@ -129,13 +174,21 @@ export async function launchPublishToDockerContainerQuickpick(project: Project):
return undefined;
}
const eulaAccepted = await launchEulaQuickPick(baseImage);
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: baseImage,
dockerBaseImageEula: imageInfo?.agreementInfo?.link?.url || ''
};
let deploySettings = await getPublishDatabaseSettings(project, false);

View File

@@ -14,7 +14,7 @@ import { IDeploySettings } from '../models/IDeploySettings';
import { DeploymentOptions } from '../../../mssql/src/mssql';
import { IconPathHelper } from '../common/iconHelper';
import { cssStyles } from '../common/uiConstants';
import { getConnectionName, getDockerBaseImages } from './utils';
import { getAgreementDisplayText, getConnectionName, getDockerBaseImages } from './utils';
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
import { IDeployProfile } from '../models/deploy/deployProfile';
import { Deferred } from '../common/promise';
@@ -35,6 +35,7 @@ export class PublishDatabaseDialog {
private connectionsRadioButton: azdataType.RadioButtonComponent | undefined;
private existingServerRadioButton: azdataType.RadioButtonComponent | undefined;
private dockerServerRadioButton: azdataType.RadioButtonComponent | undefined;
private eulaCheckBox: azdataType.CheckBoxComponent | undefined;
private dataSourcesRadioButton: azdataType.RadioButtonComponent | undefined;
private sqlCmdVariablesTable: azdataType.DeclarativeTableComponent | undefined;
private sqlCmdVariablesFormComponentGroup: azdataType.FormComponentGroup | undefined;
@@ -230,10 +231,14 @@ export class PublishDatabaseDialog {
utils.getAzdataApi()!.window.closeDialog(this.dialog);
await this.publish!(this.project, settings);
} else {
const dockerBaseImage = this.getBaseDockerImageName();
const baseImages = getDockerBaseImages();
const imageInfo = baseImages.find(x => x.name === dockerBaseImage);
const settings: IDeployProfile = {
localDbSetting: {
dbName: this.targetDatabaseName,
dockerBaseImage: this.getBaseDockerImageName(),
dockerBaseImage: dockerBaseImage,
dockerBaseImageEula: imageInfo?.agreementInfo?.link?.url || '',
password: this.serverAdminPasswordTextBox?.value || '',
port: +(this.serverPortTextBox?.value || constants.defaultPortNumber),
serverName: constants.defaultLocalServerName,
@@ -570,21 +575,49 @@ export class PublishDatabaseDialog {
});
this.serverConfigAdminPasswordTextBox.onTextChanged(() => {
this.tryEnableGenerateScriptAndOkButtons();
});
const serverConfirmPasswordRow = this.createFormRow(view, constants.confirmServerPassword, this.serverConfigAdminPasswordTextBox);
const baseImages = getDockerBaseImages();
this.baseDockerImageDropDown = view.modelBuilder.dropDown().withProps({
values: getDockerBaseImages(),
values: baseImages.map(x => x.name),
ariaLabel: constants.baseDockerImage,
width: cssStyles.publishDialogTextboxWidth,
enabled: true
}).component();
const agreementInfo = baseImages[0].agreementInfo;
const dropDownRow = this.createFormRow(view, constants.baseDockerImage, this.baseDockerImageDropDown);
this.eulaCheckBox = view.modelBuilder.checkBox().withProps({
ariaLabel: getAgreementDisplayText(agreementInfo),
required: true
}).component();
this.eulaCheckBox.onChanged(() => {
this.tryEnableGenerateScriptAndOkButtons();
});
const eulaRow = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
this.localDbSection = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
this.localDbSection.addItems([serverPortRow, serverPasswordRow, serverConfirmPasswordRow, dropDownRow]);
this.localDbSection.addItems([serverPortRow, serverPasswordRow, serverConfirmPasswordRow, dropDownRow, eulaRow]);
this.baseDockerImageDropDown.onValueChanged(() => {
if (this.eulaCheckBox) {
this.eulaCheckBox.checked = false;
}
const baseImage = getDockerBaseImages().find(x => x.name === this.baseDockerImageDropDown?.value);
if (baseImage?.agreementInfo.link) {
const text = view.modelBuilder.text().withProps({
value: constants.eulaAgreementTemplate,
links: [baseImage.agreementInfo.link],
requiredIndicator: true
}).component();
if (eulaRow && this.eulaCheckBox) {
eulaRow?.clearItems();
eulaRow?.addItems([this.eulaCheckBox, text], { flex: '0 0 auto', CSSStyles: { 'margin-right': '10px' } });
}
}
});
return this.localDbSection;
}
@@ -835,7 +868,8 @@ export class PublishDatabaseDialog {
} else if (utils.validateSqlServerPortNumber(this.serverPortTextBox?.value) &&
!utils.isEmptyString(this.serverAdminPasswordTextBox?.value) &&
utils.isValidSQLPassword(this.serverAdminPasswordTextBox?.value || '', constants.defaultLocalServerAdminName) &&
this.serverAdminPasswordTextBox?.value === this.serverConfigAdminPasswordTextBox?.value) {
this.serverAdminPasswordTextBox?.value === this.serverConfigAdminPasswordTextBox?.value
&& this.eulaCheckBox?.checked) {
publishEnabled = true; // only publish is supported for container
}

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as constants from '../common/constants';
import { AgreementInfo, DockerImageInfo } from '../models/deploy/deployProfile';
/**
* Gets connection name from connection object if there is one,
@@ -25,11 +26,38 @@ export function getConnectionName(connection: any): string {
return connectionName;
}
export function getAgreementDisplayText(agreementInfo: AgreementInfo): string {
return constants.eulaAgreementText(agreementInfo.link!.text);
}
export function getDockerBaseImages(): string[] {
export function getDockerBaseImages(): DockerImageInfo[] {
return [
`${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2017-latest`,
`${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2019-latest`,
`${constants.sqlServerDockerRegistry}/${constants.azureSqlEdgeDockerRepository}:latest`
{
name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2017-latest`,
agreementInfo: {
link: {
text: constants.eulaAgreementTitle,
url: constants.sqlServerEulaLink,
}
}
},
{
name: `${constants.sqlServerDockerRegistry}/${constants.sqlServerDockerRepository}:2019-latest`,
agreementInfo: {
link: {
text: constants.eulaAgreementTitle,
url: constants.sqlServerEulaLink,
}
}
},
{
name: `${constants.sqlServerDockerRegistry}/${constants.azureSqlEdgeDockerRepository}:latest`,
agreementInfo: {
link: {
text: constants.edgeEulaAgreementTitle,
url: constants.sqlServerEdgeEulaLink,
}
}
},
];
}