mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Remove azdata eula acceptance from arc deployments (#12292)
* saving to switch tasks * activate to exports in extApi * working version - cleanup pending * improve messages * apply pr feedback from a different review * remove unneeded strings * redo apiService * remove async from getVersionFromOutput * remove _ prefix from protected fields * error message fix * throw specif errors from azdata extension * arrow methods to regular methods * pr feedback * expand azdata extension api * pr feedback * remove unused var * pr feedback
This commit is contained in:
@@ -502,18 +502,20 @@
|
||||
"dependencies": {
|
||||
"linux-release-info": "^2.0.0",
|
||||
"promisify-child-process": "^3.1.1",
|
||||
"semver": "^7.3.2",
|
||||
"sudo-prompt": "9.1.1",
|
||||
"vscode-nls": "^4.0.0",
|
||||
"yamljs": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^5.2.5",
|
||||
"@types/semver": "^7.3.1",
|
||||
"@types/yamljs": "0.2.30",
|
||||
"mocha": "^5.2.0",
|
||||
"mocha-junit-reporter": "^1.17.0",
|
||||
"mocha-multi-reporters": "^1.1.7",
|
||||
"should": "^13.2.3",
|
||||
"typemoq": "^2.1.0",
|
||||
"vscodetestcover": "^1.1.0",
|
||||
"should": "^13.2.3"
|
||||
"vscodetestcover": "^1.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,6 +388,7 @@ export interface ITool {
|
||||
finishInitialization(): Promise<void>;
|
||||
install(): Promise<void>;
|
||||
isSameOrNewerThan(version: string): boolean;
|
||||
validateEula(): boolean;
|
||||
}
|
||||
|
||||
export const enum BdcDeploymentType {
|
||||
|
||||
@@ -34,3 +34,4 @@ export const optionsNotDefined = (fieldType: FieldType) => localize('optionsNotD
|
||||
export const optionsNotObjectOrArray = localize('optionsNotObjectOrArray', "FieldInfo.options must be an object if it is not an array");
|
||||
export const optionsTypeNotFound = localize('optionsTypeNotFound', "When FieldInfo.options is an object it must have 'optionsType' property");
|
||||
export const optionsTypeRadioOrDropdown = localize('optionsTypeRadioOrDropdown', "When optionsType is not {0} then it must be {1}", OptionsType.Radio, OptionsType.Dropdown);
|
||||
export const azdataEulaNotAccepted = localize('azdataEulaNotAccepted', "Deployment cannot continue. Azure Data CLI license terms have not been accepted. Execute the command: [Azure Data CLI: Accept EULA] to accept EULA to enable the features that requires Azure Data CLI.");
|
||||
|
||||
@@ -3,18 +3,21 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as arc from 'arc';
|
||||
import * as azdataExt from 'azdata-ext';
|
||||
import * as azurecore from 'azurecore';
|
||||
import * as vscode from 'vscode';
|
||||
import * as arc from 'arc';
|
||||
|
||||
export interface IApiService {
|
||||
readonly azurecoreApi: azurecore.IExtension;
|
||||
readonly azdataApi: azdataExt.IExtension;
|
||||
readonly arcApi: arc.IExtension;
|
||||
}
|
||||
|
||||
class ApiService implements IApiService {
|
||||
constructor() { }
|
||||
public get azurecoreApi() { return vscode.extensions.getExtension(azurecore.extension.name)?.exports; }
|
||||
public get azdataApi() { return vscode.extensions.getExtension(azdataExt.extension.name)?.exports; }
|
||||
public get arcApi() { return vscode.extensions.getExtension(arc.extension.name)?.exports; }
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,11 @@ import { SemVer } from 'semver';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { AzdataInstallLocationKey, DeploymentConfigurationKey } from '../../constants';
|
||||
import { Command, OsDistribution, ToolType } from '../../interfaces';
|
||||
import { Command, OsDistribution, ToolStatus, ToolType } from '../../interfaces';
|
||||
import { apiService } from '../apiService';
|
||||
import { IPlatformService } from '../platformService';
|
||||
import { dependencyType, ToolBase } from './toolBase';
|
||||
import { SemVerProxy } from './SemVerProxy';
|
||||
import * as loc from '../../localizedConstants';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
export const AzdataToolName = 'azdata';
|
||||
@@ -44,25 +45,57 @@ export class AzdataTool extends ToolBase {
|
||||
return 'https://docs.microsoft.com/sql/big-data-cluster/deploy-install-azdata';
|
||||
}
|
||||
|
||||
public validateEula(): boolean {
|
||||
if (apiService.azdataApi.isEulaAccepted()) {
|
||||
return true;
|
||||
} else {
|
||||
this.setStatusDescription(loc.azdataEulaNotAccepted);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* unused */
|
||||
protected get versionCommand(): Command {
|
||||
return {
|
||||
command: 'azdata -v'
|
||||
command: ''
|
||||
};
|
||||
}
|
||||
|
||||
/* unused */
|
||||
protected get discoveryCommand(): Command {
|
||||
return {
|
||||
command: this.discoveryCommandString('azdata')
|
||||
command: ''
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* updates the version and status for the tool.
|
||||
*/
|
||||
protected async updateVersionAndStatus(): Promise<void> {
|
||||
this.setStatusDescription('');
|
||||
await this.addInstallationSearchPathsToSystemPath();
|
||||
|
||||
const commandOutput = await apiService.azdataApi.azdata.version();
|
||||
this.version = apiService.azdataApi.azdata.getSemVersion();
|
||||
if (this.version) {
|
||||
if (this.autoInstallSupported) {
|
||||
// set the installationPath
|
||||
this.setInstallationPathOrAdditionalInformation(apiService.azdataApi.azdata.getPath());
|
||||
}
|
||||
this.setStatus(ToolStatus.Installed);
|
||||
}
|
||||
else {
|
||||
this.setInstallationPathOrAdditionalInformation(localize('deployCluster.GetToolVersionErrorInformation', "Error retrieving version information. See output channel '{0}' for more details", this.outputChannelName));
|
||||
this.setStatusDescription(localize('deployCluster.GetToolVersionError', "Error retrieving version information.{0}Invalid output received, get version command output: '{1}' ", EOL, commandOutput.stderr.join(EOL)));
|
||||
this.setStatus(ToolStatus.NotInstalled);
|
||||
}
|
||||
}
|
||||
|
||||
protected getVersionFromOutput(output: string): SemVer | undefined {
|
||||
let version: SemVer | undefined = undefined;
|
||||
if (output && output.split(EOL).length > 0) {
|
||||
version = new SemVerProxy(output.split(EOL)[0].replace(/ /g, ''));
|
||||
}
|
||||
return version;
|
||||
return apiService.azdataApi.azdata.getSemVersion();
|
||||
|
||||
}
|
||||
|
||||
protected async getSearchPaths(): Promise<string[]> {
|
||||
switch (this.osDistribution) {
|
||||
case OsDistribution.win32:
|
||||
|
||||
@@ -58,6 +58,8 @@ export abstract class ToolBase implements ITool {
|
||||
|
||||
protected abstract readonly versionCommand: Command;
|
||||
|
||||
public validateEula(): boolean { return true; }
|
||||
|
||||
public get dependencyMessages(): string[] {
|
||||
return (this.dependenciesByOsType.get(this.osDistribution) || []).map((msgType: dependencyType) => messageByDependencyType.get(msgType)!);
|
||||
}
|
||||
@@ -126,10 +128,18 @@ export abstract class ToolBase implements ITool {
|
||||
return this._statusDescription;
|
||||
}
|
||||
|
||||
protected setStatusDescription(value: string | undefined): void {
|
||||
this._statusDescription = value;
|
||||
}
|
||||
|
||||
public get installationPathOrAdditionalInformation(): string | undefined {
|
||||
return this._installationPathOrAdditionalInformation;
|
||||
}
|
||||
|
||||
protected setInstallationPathOrAdditionalInformation(value: string | undefined) {
|
||||
this._installationPathOrAdditionalInformation = value;
|
||||
}
|
||||
|
||||
protected get installationCommands(): Command[] | undefined {
|
||||
return this.allInstallationCommands.get(this.osDistribution);
|
||||
}
|
||||
@@ -250,7 +260,7 @@ export abstract class ToolBase implements ITool {
|
||||
/**
|
||||
* updates the version and status for the tool.
|
||||
*/
|
||||
private async updateVersionAndStatus(): Promise<void> {
|
||||
protected async updateVersionAndStatus(): Promise<void> {
|
||||
this._statusDescription = '';
|
||||
await this.addInstallationSearchPathsToSystemPath();
|
||||
const commandOutput = await this.platformService.runCommand(
|
||||
@@ -306,7 +316,7 @@ export abstract class ToolBase implements ITool {
|
||||
}
|
||||
|
||||
isSameOrNewerThan(version?: string): boolean {
|
||||
return !version || (this._version ? SemVerCompare(this._version, version) >= 0 : false);
|
||||
return !version || (this._version ? SemVerCompare(this._version.raw, version) >= 0 : false);
|
||||
}
|
||||
|
||||
private _pendingVersionAndStatusUpdate!: Promise<void>;
|
||||
|
||||
@@ -8,7 +8,6 @@ import assert = require('assert');
|
||||
import { apiService } from '../services/apiService';
|
||||
|
||||
suite('API Service Tests', function (): void {
|
||||
|
||||
test('getAzurecoreApi returns azure api', () => {
|
||||
const api = apiService.azurecoreApi;
|
||||
assert(api !== undefined);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
/// <reference path='../../../../src/sql/azdata.d.ts'/>
|
||||
/// <reference path='../../../../src/sql/azdata.proposed.d.ts'/>
|
||||
/// <reference path='../../../arc/src/typings/arc.d.ts'/>
|
||||
/// <reference path='../../../azdata/src/typings/azdata-ext.d.ts'/>
|
||||
/// <reference path='../../../azurecore/src/azurecore.d.ts'/>
|
||||
/// <reference path='../../../azurecore/src/azureResource/azure-resource.d.ts'/>
|
||||
/// <reference types='@types/node'/>
|
||||
|
||||
@@ -26,6 +26,7 @@ export class ResourceTypePickerDialog extends DialogBase {
|
||||
private _agreementContainer!: azdata.DivContainer;
|
||||
private _agreementCheckboxChecked: boolean = false;
|
||||
private _installToolButton: azdata.window.Button;
|
||||
private _recheckEulaButton: azdata.window.Button;
|
||||
private _installationInProgress: boolean = false;
|
||||
private _tools: ITool[] = [];
|
||||
|
||||
@@ -37,10 +38,15 @@ export class ResourceTypePickerDialog extends DialogBase {
|
||||
super(localize('resourceTypePickerDialog.title', "Select the deployment options"), 'ResourceTypePickerDialog', true);
|
||||
this._selectedResourceType = defaultResourceType;
|
||||
this._installToolButton = azdata.window.createButton(localize('deploymentDialog.InstallToolsButton', "Install tools"));
|
||||
this._recheckEulaButton = azdata.window.createButton(localize('deploymentDialog.RecheckEulaButton', "Validate EULA"));
|
||||
this._toDispose.push(this._installToolButton.onClick(() => {
|
||||
this.installTools().catch(error => console.log(error));
|
||||
}));
|
||||
this._dialogObject.customButtons = [this._installToolButton];
|
||||
this._toDispose.push(this._recheckEulaButton.onClick(() => {
|
||||
this._dialogObject.message = { text: '' }; // clear any previous message.
|
||||
this._dialogObject.okButton.enabled = this.validateToolsEula(); // re-enable the okButton if validation succeeds.
|
||||
}));
|
||||
this._dialogObject.customButtons = [this._installToolButton, this._recheckEulaButton];
|
||||
this._installToolButton.hidden = true;
|
||||
this._dialogObject.okButton.label = localize('deploymentDialog.OKButtonText', "Select");
|
||||
this._dialogObject.okButton.enabled = false; // this is enabled after all tools are discovered.
|
||||
@@ -278,12 +284,12 @@ export class ResourceTypePickerDialog extends DialogBase {
|
||||
return [tool.displayName, tool.description, tool.displayStatus, tool.fullVersion || '', toolRequirement.version || '', tool.installationPathOrAdditionalInformation || ''];
|
||||
});
|
||||
this._installToolButton.hidden = erroredOrFailedTool || minVersionCheckFailed || (toolsToAutoInstall.length === 0);
|
||||
this._dialogObject.okButton.enabled = !erroredOrFailedTool && messages.length === 0 && !minVersionCheckFailed && (toolsToAutoInstall.length === 0);
|
||||
this._dialogObject.okButton.enabled = !erroredOrFailedTool && messages.length === 0 && !minVersionCheckFailed && (toolsToAutoInstall.length === 0) && this.validateToolsEula();
|
||||
if (messages.length !== 0) {
|
||||
if (messages.length > 1) {
|
||||
messages = messages.map(message => `• ${message}`);
|
||||
}
|
||||
messages.push(localize('deploymentDialog.VersionInformationDebugHint', "You will need to restart Azure Data Studio if the tools are installed manually after Azure Data Studio is launched to pick up the updated PATH environment variable. You may find additional details in 'Deployments' output channel"));
|
||||
messages.push(localize('deploymentDialog.VersionInformationDebugHint', "You will need to restart Azure Data Studio if the tools are installed manually to pick up the change. You may find additional details in 'Deployments' and 'azdata' output channels"));
|
||||
this._dialogObject.message = {
|
||||
level: azdata.window.MessageLevel.Error,
|
||||
text: messages.join(EOL)
|
||||
@@ -313,6 +319,21 @@ export class ResourceTypePickerDialog extends DialogBase {
|
||||
this._toolsLoadingComponent.loading = false;
|
||||
}
|
||||
|
||||
private validateToolsEula(): boolean {
|
||||
const validationSucceeded = this._tools.every(tool => {
|
||||
const eulaValidated = tool.validateEula();
|
||||
if (!eulaValidated) {
|
||||
this._dialogObject.message = {
|
||||
level: azdata.window.MessageLevel.Error,
|
||||
text: tool.statusDescription!
|
||||
};
|
||||
}
|
||||
return eulaValidated;
|
||||
});
|
||||
this._recheckEulaButton.hidden = validationSucceeded;
|
||||
return validationSucceeded;
|
||||
}
|
||||
|
||||
private get toolRequirements() {
|
||||
return this.getCurrentProvider().requiredTools;
|
||||
}
|
||||
|
||||
@@ -194,6 +194,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea"
|
||||
integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==
|
||||
|
||||
"@types/semver@^7.3.1":
|
||||
version "7.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb"
|
||||
integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ==
|
||||
|
||||
"@types/yamljs@0.2.30":
|
||||
version "0.2.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/yamljs/-/yamljs-0.2.30.tgz#d034e1d329e46e8d0f737c9a8db97f68f81b5382"
|
||||
@@ -694,6 +699,11 @@ semver@^6.0.0, semver@^6.3.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
semver@^7.3.2:
|
||||
version "7.3.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
||||
|
||||
should-equal@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3"
|
||||
|
||||
Reference in New Issue
Block a user