From f999caecafd6eebe2a3df3646dd753baa0c2618b Mon Sep 17 00:00:00 2001 From: Kanika Pasrija Date: Fri, 17 Apr 2020 15:34:47 +0530 Subject: [PATCH 1/2] handling right click scenario --- .../clients/github/TemplateServiceClient.ts | 2 +- src/configure/configure.ts | 44 +++++++------- .../utilities/InputControlProvider.ts | 59 +++++++++++-------- src/configure/utilities/InputUxDescriptor.ts | 31 ++++++++-- 4 files changed, 82 insertions(+), 54 deletions(-) diff --git a/src/configure/clients/github/TemplateServiceClient.ts b/src/configure/clients/github/TemplateServiceClient.ts index 7453f41b..763dc0b1 100644 --- a/src/configure/clients/github/TemplateServiceClient.ts +++ b/src/configure/clients/github/TemplateServiceClient.ts @@ -155,7 +155,7 @@ export class TemplateServiceClient { "isRequired": true, "sublabel": null, "properties": { - "cdResource": "true" + "deployTarget": "true" }, "inputMode": 80, "dataSourceId": "listExistingAKS", diff --git a/src/configure/configure.ts b/src/configure/configure.ts index 0e1d31ab..6fffd72c 100644 --- a/src/configure/configure.ts +++ b/src/configure/configure.ts @@ -23,7 +23,7 @@ import * as constants from './resources/constants'; import { Messages } from './resources/messages'; import { TelemetryKeys } from './resources/telemetryKeys'; import { TracePoints } from './resources/tracePoints'; -import { InputControlProvider as InputControlProvider} from './utilities/InputControlProvider'; +import { InputControlProvider as InputControlProvider } from './utilities/InputControlProvider'; const Layer: string = 'configure'; export let UniqueResourceNameSuffix: string = uuid().substr(0, 5); @@ -121,16 +121,16 @@ class Orchestrator { await this.getAzureSession(); await this.getSelectedPipeline(); - - if(this.inputs.pipelineConfiguration.templateInfo){ + + if (this.inputs.pipelineConfiguration.templateInfo) { //this.inputs.pipelineConfiguration.template.extendedPipelineTemplate = - let extendedPipelineTemplate = await templateHelper.getTemplateParameteres(this.inputs.pipelineConfiguration.templateInfo); - let inputs:{ [key: string]: any} = {}; + let extendedPipelineTemplate = await templateHelper.getTemplateParameteres(this.inputs.pipelineConfiguration.templateInfo); + let inputs: { [key: string]: any } = {}; inputs['subscriptionId'] = this.inputs.subscriptionId; let controlProvider = new InputControlProvider(extendedPipelineTemplate, inputs); - this.inputs.pipelineConfiguration.parameters = await controlProvider.getAllInputUxDescriptors(this.inputs.azureSession); + this.inputs.pipelineConfiguration.parameters = await controlProvider.getAllInputUxDescriptors(this.inputs.azureSession, resourceNode); } - else{ + else { if (this.inputs.pipelineConfiguration.template.label === "Containerized application to AKS") { // try to see if node corresponds to any parameter of selected pipeline. if (resourceNode) { @@ -139,7 +139,7 @@ class Orchestrator { this.inputs.pipelineConfiguration.params[resourceParam.name] = resourceNode; } } - + try { let templateParameterHelper = new TemplateParameterHelper(); await templateParameterHelper.setParameters(this.inputs.pipelineConfiguration.template.parameters, this.inputs); @@ -160,7 +160,7 @@ class Orchestrator { } } } - + } } @@ -210,7 +210,7 @@ class Orchestrator { workspaceFolderOptions, { placeHolder: Messages.selectWorkspaceFolder }); this.workspacePath = selectedWorkspaceFolder.data.uri.fsPath; - } + } } else { telemetryHelper.setTelemetry(TelemetryKeys.SourceRepoLocation, SourceOptions.BrowseLocalMachine); @@ -423,7 +423,7 @@ class Orchestrator { private async getSelectedPipeline(): Promise { var repoAnalysisHelper = new RepoAnalysisHelper(this.inputs.azureSession); - var repoAnalysisResult = await repoAnalysisHelper.getRepositoryAnalysis(this.inputs.sourceRepository, + var repoAnalysisResult = await repoAnalysisHelper.getRepositoryAnalysis(this.inputs.sourceRepository, this.inputs.pipelineConfiguration.workingDirectory.split('/').join('\\')); extensionVariables.templateServiceEnabled = false; @@ -487,7 +487,7 @@ class Orchestrator { //Post selecting the template update this.inputs.repositoryAnalysisApplicationSettings with corresponding languageSettings if (!!repoAnalysisResult && !!repoAnalysisResult.repositoryAnalysisApplicationSettingsList) { - + //Get languageSettings (corresponding to language of selected settings) provided by RepoAnalysis await this.updateRepositoryAnalysisApplicationSettings(repoAnalysisResult); } @@ -500,17 +500,17 @@ class Orchestrator { } } - private async updateRepositoryAnalysisApplicationSettings(repoAnalysisResult: RepositoryAnalysisParameters): Promise{ + private async updateRepositoryAnalysisApplicationSettings(repoAnalysisResult: RepositoryAnalysisParameters): Promise { var applicationSettings = repoAnalysisResult.repositoryAnalysisApplicationSettingsList.filter(applicationSetting => { return applicationSetting.language === this.inputs.pipelineConfiguration.template.language; }); - - if(!applicationSettings || applicationSettings.length == 0){ + + if (!applicationSettings || applicationSettings.length == 0) { return; } let workspacePaths = Array.from(new Set(applicationSettings.map(a => a.settings.workingDirectory))); - if(workspacePaths.length == 1){ + if (workspacePaths.length == 1) { this.inputs.repositoryAnalysisApplicationSettings = applicationSettings[0]; this.inputs.pipelineConfiguration.workingDirectory = applicationSettings[0].settings.workingDirectory; return; @@ -524,13 +524,13 @@ class Orchestrator { constants.SelectWorkspace, workspacePathQuickPickItemList, { placeHolder: Messages.selectWorkspace }); - + this.inputs.pipelineConfiguration.workingDirectory = selectedWorkspacePathItem.data; - this.inputs.repositoryAnalysisApplicationSettings = - repoAnalysisResult.repositoryAnalysisApplicationSettingsList.find(applicationSettings => { - return (applicationSettings.language === this.inputs.pipelineConfiguration.template.language - && applicationSettings.settings.workingDirectory === selectedWorkspacePathItem.data); - }); + this.inputs.repositoryAnalysisApplicationSettings = + repoAnalysisResult.repositoryAnalysisApplicationSettingsList.find(applicationSettings => { + return (applicationSettings.language === this.inputs.pipelineConfiguration.template.language + && applicationSettings.settings.workingDirectory === selectedWorkspacePathItem.data); + }); } private async checkInPipelineFileToRepository(pipelineConfigurer: Configurer): Promise { diff --git a/src/configure/utilities/InputControlProvider.ts b/src/configure/utilities/InputControlProvider.ts index beec9a61..48ffe4fa 100644 --- a/src/configure/utilities/InputControlProvider.ts +++ b/src/configure/utilities/InputControlProvider.ts @@ -1,5 +1,6 @@ +import { GenericResource } from "azure-arm-resource/lib/resource/models"; import { MustacheHelper } from "../helper/mustacheHelper"; -import {ExtendedInputDescriptor, ExtendedPipelineTemplate, InputMode } from "../model/Contracts"; +import { ExtendedInputDescriptor, ExtendedPipelineTemplate, InputMode } from "../model/Contracts"; import { AzureSession, ControlType, IPredicate, StringMap } from '../model/models'; import { DataSourceExpression } from "./DataSourceExpression"; import { InputUxDescriptor } from "./InputUxDescriptor"; @@ -8,44 +9,50 @@ import { VisibilityHelper } from "./VisibilityHelper"; export class InputControlProvider { private _pipelineTemplate: ExtendedPipelineTemplate; - private _inputUxDescriptors: Map; - private _uxInputs: Map; + private _inputUxDescriptors: Map; + private _uxInputs: Map; - constructor(pipelineTemplateParameters: ExtendedPipelineTemplate, inputs: { [key: string]: any}){ + constructor(pipelineTemplateParameters: ExtendedPipelineTemplate, inputs: { [key: string]: any }) { this._pipelineTemplate = pipelineTemplateParameters; this._inputUxDescriptors = new Map(); this._uxInputs = new Map(); this._createControls(inputs); } - public async getAllInputUxDescriptors(azureSession: AzureSession ) { - let parameters: { [key: string]: any} = {}; - for(let inputUxDescriptor of this._inputUxDescriptors.values()){ - this._setInputUxVisibility(inputUxDescriptor); - this._setupDefaultInputValue(inputUxDescriptor); - await inputUxDescriptor.setInputUxDescriptorValue(azureSession); + public async getAllInputUxDescriptors(azureSession: AzureSession, resourceNode?: GenericResource) { + let parameters: { [key: string]: any } = {}; + + for (let inputUxDescriptor of this._inputUxDescriptors.values()) { + if (inputUxDescriptor.getPropertyValue('deployTarget') === "true" && !!resourceNode) { + inputUxDescriptor.updateValue(resourceNode.id); + } + else { + this._setInputUxVisibility(inputUxDescriptor); + this._setupDefaultInputValue(inputUxDescriptor); + await inputUxDescriptor.setInputUxDescriptorValue(azureSession); + } parameters[inputUxDescriptor.getInputUxDescriptorId()] = inputUxDescriptor.getParameterValue(); } return parameters; } - private _createControls(inputValues: { [key: string]: any}) { - for( let input of this._pipelineTemplate.inputs){ + private _createControls(inputValues: { [key: string]: any }) { + for (let input of this._pipelineTemplate.inputs) { this._uxInputs.set(input.id, input); var inputUxDescriptor: InputUxDescriptor = null; var inputUxDescriptorValue = this._getInputUxDescriptorValue(input, inputValues); - if(input.groupId === 'cdResource' && input.properties.cdResource){ + if (input.groupId === 'cdResource' && input.properties.deployTarget) { input.inputMode = InputMode.Combo; } - switch(input.inputMode){ - case InputMode.None: + switch (input.inputMode) { + case InputMode.None: // here we'll use data source id to get value - inputUxDescriptor = new InputUxDescriptor(input,inputUxDescriptorValue, ControlType.None); + inputUxDescriptor = new InputUxDescriptor(input, inputUxDescriptorValue, ControlType.None); break; case InputMode.TextBox: case InputMode.PasswordBox: - inputUxDescriptor = new InputUxDescriptor(input,inputUxDescriptorValue, ControlType.InputBox); + inputUxDescriptor = new InputUxDescriptor(input, inputUxDescriptorValue, ControlType.InputBox); break; case InputMode.Combo: case InputMode.CheckBox: @@ -55,11 +62,11 @@ export class InputControlProvider { break; } - if(inputUxDescriptor){ + if (inputUxDescriptor) { this._inputUxDescriptors.set(input.id, inputUxDescriptor); } } - this._setUxDescriptorsDataSourceInputs(); + this._setUxDescriptorsDataSourceInputs(); } private _setUxDescriptorsDataSourceInputs(): void { @@ -94,7 +101,7 @@ export class InputControlProvider { } } - + private _computeMustacheValue(mustacheExpression: string, dependentUxDesciptorArray: InputUxDescriptor[]): string { var dependentInputValues = this._getInputParameterValueIfAllSet(dependentUxDesciptorArray); @@ -105,17 +112,17 @@ export class InputControlProvider { } } - private _getInputUxDescriptorValue(inputDes: ExtendedInputDescriptor, inputValues: { [key:string]:any }) { + private _getInputUxDescriptorValue(inputDes: ExtendedInputDescriptor, inputValues: { [key: string]: any }) { if (!!inputValues && !!inputValues[inputDes.id]) { return inputValues[inputDes.id]; } else { return !inputDes.defaultValue - || InputUxDescriptorUtility.doesExpressionContainsDependency(inputDes.defaultValue) - ? "" : inputDes.defaultValue; + || InputUxDescriptorUtility.doesExpressionContainsDependency(inputDes.defaultValue) + ? "" : inputDes.defaultValue; } } - private _getInputDependencyArray(inputUxDescriptor: InputUxDescriptor, dependencyExpressionArray: string[], allowSelfDependency: boolean = true){ + private _getInputDependencyArray(inputUxDescriptor: InputUxDescriptor, dependencyExpressionArray: string[], allowSelfDependency: boolean = true) { var dependentInputUxDescriptorArray: InputUxDescriptor[] = []; var dependentInputIds: string[] = []; for (var dependencyExpression of dependencyExpressionArray) { @@ -134,7 +141,7 @@ export class InputControlProvider { var uniqueDependentInputIds = dependentInputIds.filter(function (item, pos) { return dependentInputIds.indexOf(item) === pos; - }); + }); for (var inputId of uniqueDependentInputIds) { var dependentInputUxDescriptor = this._inputUxDescriptors.get(inputId); @@ -156,7 +163,7 @@ export class InputControlProvider { for (var dependentUxDesciptor of dependentUxDesciptorArray) { if (!dependentUxDesciptor.getParameterValue()) { //Value of the parameter is not available, so rest of the input values will be useless. - throw new Error("Unable to get the input value") ; + throw new Error("Unable to get the input value"); } inputs[dependentUxDesciptor.getInputUxDescriptorId()] = dependentUxDesciptor.getParameterValue(); } diff --git a/src/configure/utilities/InputUxDescriptor.ts b/src/configure/utilities/InputUxDescriptor.ts index 0fd1ec5e..484e781b 100644 --- a/src/configure/utilities/InputUxDescriptor.ts +++ b/src/configure/utilities/InputUxDescriptor.ts @@ -1,7 +1,8 @@ import { InputBoxOptions, QuickPickItem } from 'vscode'; import { IAzureQuickPickOptions } from 'vscode-azureextensionui'; +import { MustacheHelper } from '../helper/mustacheHelper'; import { ExtendedInputDescriptor, InputMode } from "../model/Contracts"; -import { AzureSession, ControlType, extensionVariables } from '../model/models'; +import { AzureSession, ControlType, extensionVariables, StringMap } from '../model/models'; import { Messages } from '../resources/messages'; import { DataSourceExpression } from './DataSourceExpression'; @@ -53,16 +54,17 @@ export class InputUxDescriptor { } else if (this._controlType === ControlType.InputBox && this._input.isRequired) { - this._value = await this.showInputBox({ + this._value = await this.showInputBox({ placeHolder: this._input.description, validateInput: (inputValue) => { return !inputValue ? Messages.valueRequired : null; - } + } }); } else if (this._controlType === ControlType.InputBox) { - this._value = await this.showInputBox({ - placeHolder: this._input.description}); + this._value = await this.showInputBox({ + placeHolder: this._input.description + }); } } } @@ -112,6 +114,25 @@ export class InputUxDescriptor { this._isVisible = value; } + public getPropertyValue(propertyName: string, inputs?: StringMap): string { + return InputUxDescriptor.getUxDescriptorProperty(this._input, propertyName, inputs); + } + + public static getUxDescriptorProperty(inputDescriptor: ExtendedInputDescriptor, property: string, inputs?: StringMap): any { + var properties = inputDescriptor.properties; + var value: Object; + + if (!!properties) { + value = properties[property]; + if (!!value && !!inputs && typeof value === "string") { + return MustacheHelper.render(value, { inputs: inputs }); + } else if (!!value && !!inputs) { + return MustacheHelper.renderObject(value, { inputs: inputs }); + } + } + return value; + } + private async showQuickPick(listItems: T[] | Thenable, options: IAzureQuickPickOptions, itemCountTelemetryKey?: string): Promise { try { //telemetryHelper.setTelemetry(TelemetryKeys.CurrentUserInput, listName); From af102b065270e331fd74b9eb8c9dfb5e6782ee92 Mon Sep 17 00:00:00 2001 From: Kanika Pasrija Date: Tue, 21 Apr 2020 18:57:02 +0530 Subject: [PATCH 2/2] resolving conflicts --- src/configure/configure.ts | 2 +- .../templateInputHelper/InputControl.ts | 18 +++++++++++++++++- .../InputControlProvider.ts | 14 ++++++++++---- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/configure/configure.ts b/src/configure/configure.ts index a1bdead9..1fa6b0bd 100644 --- a/src/configure/configure.ts +++ b/src/configure/configure.ts @@ -130,7 +130,7 @@ class Orchestrator { let context: { [key: string]: any } = {}; context['subscriptionId'] = this.inputs.subscriptionId; let controlProvider = new InputControlProvider(extendedPipelineTemplate, context); - this.inputs.pipelineConfiguration.parameters = await controlProvider.getAllPipelineTemplateInputs(this.inputs.azureSession); + this.inputs.pipelineConfiguration.parameters = await controlProvider.getAllPipelineTemplateInputs(this.inputs.azureSession, resourceNode); } else { if (this.inputs.pipelineConfiguration.template.label === "Containerized application to AKS") { diff --git a/src/configure/templateInputHelper/InputControl.ts b/src/configure/templateInputHelper/InputControl.ts index cb68b38c..b77d6c2d 100644 --- a/src/configure/templateInputHelper/InputControl.ts +++ b/src/configure/templateInputHelper/InputControl.ts @@ -1,8 +1,9 @@ import { InputBoxOptions, QuickPickItem } from 'vscode'; import { IAzureQuickPickOptions } from 'vscode-azureextensionui'; +import { MustacheHelper } from '../helper/mustacheHelper'; import { telemetryHelper } from '../helper/telemetryHelper'; import { ExtendedInputDescriptor, InputMode } from "../model/Contracts"; -import { AzureSession, ControlType, extensionVariables } from '../model/models'; +import { AzureSession, ControlType, extensionVariables, StringMap } from '../model/models'; import { Messages } from '../resources/messages'; import { TelemetryKeys } from '../resources/telemetryKeys'; import { DataSourceExpression } from './utilities/DataSourceExpression'; @@ -103,6 +104,21 @@ export class InputControl { } } + public getPropertyValue(propertyName: string, inputs?: StringMap): string { + var properties = this.inputDescriptor.properties; + var value: string; + + if (!!properties) { + value = properties[propertyName]; + if (!!value && !!inputs && typeof value === "string") { + return MustacheHelper.render(value, { inputs: inputs }); + } else if (!!value && !!inputs) { + return MustacheHelper.renderObject(value, { inputs: inputs }); + } + } + return value; + } + private _getDataSourceInputs(): { [key: string]: any } { var inputs: { [key: string]: any } = {}; for (var dataSourceInput of this.dataSourceInputControls) { diff --git a/src/configure/templateInputHelper/InputControlProvider.ts b/src/configure/templateInputHelper/InputControlProvider.ts index eef8766b..f1f24af6 100644 --- a/src/configure/templateInputHelper/InputControlProvider.ts +++ b/src/configure/templateInputHelper/InputControlProvider.ts @@ -1,3 +1,4 @@ +import { GenericResource } from "azure-arm-resource/lib/resource/models"; import { MustacheHelper } from "../helper/mustacheHelper"; import { ExtendedInputDescriptor, ExtendedPipelineTemplate, InputDataType, InputMode } from "../model/Contracts"; import { AzureSession, ControlType, IPredicate, StringMap } from '../model/models'; @@ -16,12 +17,17 @@ export class InputControlProvider { this._createControls(context); } - public async getAllPipelineTemplateInputs(azureSession: AzureSession) { + public async getAllPipelineTemplateInputs(azureSession: AzureSession, resourceNode?: GenericResource) { let parameters: { [key: string]: any } = {}; for (let inputControl of this._inputControlsMap.values()) { - this._setInputControlVisibility(inputControl); - this._setupInputControlDefaultValue(inputControl); - await inputControl.setInputControlValue(azureSession); + if (inputControl.getPropertyValue('deployTarget') === "true" && !!resourceNode) { + inputControl.setValue(resourceNode.id); + } + else { + this._setInputControlVisibility(inputControl); + this._setupInputControlDefaultValue(inputControl); + await inputControl.setInputControlValue(azureSession); + } parameters[inputControl.getInputControlId()] = inputControl.getValue(); } return parameters;