diff --git a/src/cli-command.ts b/src/cli-command.ts index a9e81691..8bf23253 100644 --- a/src/cli-command.ts +++ b/src/cli-command.ts @@ -68,7 +68,7 @@ function tknWorkspace(pipelineData: StartObject): string[] { workspace.push(`-w name=${element.name},secret=${element.workspaceName}`); } } else if (element.workspaceType === 'EmptyDirectory' || element.workspaceType === 'EmptyDir') { - workspace.push(`-w name=${element.name},emptyDir=${element.emptyDir ?? '""'}`); + workspace.push(`-w name=${element.name},emptyDir=''`); } }); return workspace; diff --git a/src/tekton/pipelinecontent.ts b/src/tekton/pipelinecontent.ts index 0ca2a795..cdd4ae86 100644 --- a/src/tekton/pipelinecontent.ts +++ b/src/tekton/pipelinecontent.ts @@ -110,15 +110,25 @@ export class PipelineContent extends TektonItem { return pipeResources; } - static async inputResources(Ref: Ref[], message: string, item: QuickPickItem): Promise { + static async inputResources(Ref: Ref[], item: QuickPickItem): Promise { + let resourceName: QuickPickItem | string; + const createPipelineResource = '$(plus) Create Pipeline Resource.' const RefName: QuickPickItem[] = Ref.map(label => ({ label: label.name })); + RefName.unshift({label: createPipelineResource}) const name = item['resourceGitImageType'].charAt(0).toUpperCase() + item['resourceGitImageType'].slice(1) - const pick = await multiStepInput.showQuickPick({ + resourceName = await multiStepInput.showQuickPick({ title: `${name} Resource: ${item['label']}`, - placeholder: `Select ${message} Resources`, + placeholder: 'Select Pipeline Resources', items: RefName, }); - return pick.label; + if (resourceName.label === createPipelineResource) { + resourceName = await multiStepInput.showInputBox({ + title: `${name} Resource: ${item['label']}`, + prompt: 'Please provide Name/URL', + validate: PipelineContent.validateInput, + }); + } + return (resourceName['label']) ? resourceName['label'] : resourceName; } static async inputParameters(context: Trigger[], params: QuickPickItem[], message: string): Promise { @@ -126,25 +136,14 @@ export class PipelineContent extends TektonItem { for (const item of params) { const selectedParam = context[0].params.find(x => x.name === item.label); const title = `Params: ${item['label']}`; - const paramVal = await PipelineContent.getParamValues(selectedParam.name); if (!selectedParam.default) { - const pick = await multiStepInput.showQuickPick({ + const inputVal = await multiStepInput.showInputBox({ title, - placeholder: `Select ${message} Parameter`, - items: paramVal, + prompt: `Input ${message} default Value`, + validate: PipelineContent.validateInput, }); - if (pick.label === selectedParam.name) { - const parameter: Params = { name: selectedParam.name, description: selectedParam.description, default: selectedParam.default }; - paramData.push(parameter); - } else { - const inputVal = await multiStepInput.showInputBox({ - title, - prompt: `Input ${message} default Value`, - validate: PipelineContent.validateInput, - }); - const parameter: Params = { name: selectedParam.name, description: selectedParam.description, default: inputVal }; - paramData.push(parameter); - } + const parameter: Params = { name: selectedParam.name, description: selectedParam.description, default: inputVal }; + paramData.push(parameter); } else { const parameter: Params = { name: selectedParam.name, description: selectedParam.description, default: selectedParam.default }; paramData.push(parameter); @@ -153,14 +152,9 @@ export class PipelineContent extends TektonItem { return paramData; } - static async getParamValues(paramName: string): Promise | null { - return ['$(plus) Input New Param Value', paramName] - .map(label => ({ label })); - } - static async validateInput(name: string): Promise { - const alphaNumHyph = new RegExp(/^[a-zA-Z0-9-_]+$/); - return name.match(alphaNumHyph) ? undefined : 'invalid'; + const alphaNum = new RegExp(/^[a-zA-Z0-9-_]+$/); + return name.match(alphaNum) ? undefined : 'invalid'; } static async getServiceAcct(inputStart: StartObject): Promise | null { @@ -217,19 +211,11 @@ export class PipelineContent extends TektonItem { } catch (ignore) { } const workspacesName: QuickPickItem[] | undefined = data ? data.map(label => ({ label: label['metadata'].name })) : undefined; - if (workspacesName) workspacesName.unshift({label: '$(plus) Add new workspace name.'}) workspaceName = await multiStepInput.showQuickPick({ title: `Workspace ${count}: ${item['label']}`, placeholder: `Select ${workspaceType.label}`, items: workspacesName, }); - if (workspaceName.label === '$(plus) Add new workspace name.') { - workspaceName = await multiStepInput.showInputBox({ - title: `Workspace ${count}: ${item['label']}`, - prompt: `Provide new ${workspaceType.label} name`, - validate: PipelineContent.validateInput, - }); - } if (workspaceType.label === 'ConfigMap') { key = await multiStepInput.showInputBox({ title: `Workspace ${count}: ${item['label']}`, @@ -250,21 +236,14 @@ export class PipelineContent extends TektonItem { }); } } - if (workspaceType.label === 'EmptyDir') { - emptyDir = await multiStepInput.showInputBox({ - title: `Workspace ${count}: ${item['label']}`, - prompt: 'Provide EmptyDir name', - validate: PipelineContent.validateInput, - }); - } + const selectedWorkspace: Workspaces = { name: item['label'], - workspaceName: workspaceName['label'] ? workspaceName['label'] : workspaceName, + workspaceName: workspaceName?.['label'] ? workspaceName['label'] : workspaceName, workspaceType: workspaceType.label, key: key ? key : undefined, value: value ? value : undefined, - subPath: subPath ? subPath : undefined, - emptyDir: emptyDir ? emptyDir : undefined + subPath: subPath ? subPath : undefined }; workspaceData.push(selectedWorkspace); count++; @@ -291,7 +270,7 @@ export class PipelineContent extends TektonItem { const selectedResource: Resources = { name: item['label'], resourceType: item['resourceType'], - resourceRef: await PipelineContent.inputResources(Ref, message, item), + resourceRef: await PipelineContent.inputResources(Ref, item), }; inputStart.resources.push(selectedResource); } diff --git a/test/tekton/pipelinecontent.test.ts b/test/tekton/pipelinecontent.test.ts index 3127c857..ea7c0a9d 100644 --- a/test/tekton/pipelinecontent.test.ts +++ b/test/tekton/pipelinecontent.test.ts @@ -29,10 +29,17 @@ suite('PipelineContent', () => { let showShowInputBox: sinon.SinonStub; const pipelineTrigger: Trigger[] = [{ name: 'build-and-deploy', - params: [{ - description: 'name of the deployment to be patched', - name: 'deployment-name', - }], + params: [ + { + description: 'name of the deployment to be patched', + name: 'deployment-name', + }, + { + description: 'name of the deployment to be patched', + name: 'test', + default: 'value' + } + ], resources: [{ name: 'git-repo', type: 'git' @@ -67,6 +74,9 @@ suite('PipelineContent', () => { }, { name: 'shared-data' + }, + { + name: 'test' } ] }] @@ -126,16 +136,22 @@ suite('PipelineContent', () => { test('returns pipeline start object', async () => { execStub.onFirstCall().resolves({error: undefined, stdout: resourceData}); showQuickPickStub.onFirstCall().resolves({label: 'api-repo'}); - showQuickPickStub.onSecondCall().resolves({label: 'api-image'}) - showQuickPickStub.onThirdCall().resolves({label: 'deployment-name'}); + showQuickPickStub.onSecondCall().resolves({label: '$(plus) Create Pipeline Resource.'}) + showShowInputBox.onFirstCall().resolves({label: 'api-image'}); + showShowInputBox.onSecondCall().resolves('params-data'); const result = await PipelineContent.startObject(pipelineTrigger, 'pipeline'); expect(result).deep.equals({ name: 'build-and-deploy', params: [ { - default: undefined, + default: 'params-data', description: 'name of the deployment to be patched', name: 'deployment-name' + }, + { + default: 'value', + description: 'name of the deployment to be patched', + name: 'test' } ], resources: [ @@ -159,18 +175,20 @@ suite('PipelineContent', () => { execStub.onFirstCall().resolves({error: undefined, stdout: resourceData}); showQuickPickStub.onFirstCall().resolves({label: 'api-repo'}); showQuickPickStub.onSecondCall().resolves({label: 'api-image'}) - showQuickPickStub.onThirdCall().resolves({label: '$(plus) Input New Param Value'}); - showShowInputBox.onFirstCall().resolves({label: 'params-data'}) + showShowInputBox.onFirstCall().resolves('params-data') const result = await PipelineContent.startObject(pipelineTrigger, 'pipeline'); expect(result).deep.equals({ name: 'build-and-deploy', params: [ { - default: { - label: 'params-data' - }, + default: 'params-data', description: 'name of the deployment to be patched', name: 'deployment-name' + }, + { + default: 'value', + description: 'name of the deployment to be patched', + name: 'test' } ], resources: [ @@ -228,15 +246,15 @@ suite('PipelineContent', () => { } )}); showQuickPickStub.onFirstCall().resolves({label: 'Secret'}); - showQuickPickStub.onSecondCall().resolves({label: 'secret-password'}) + showQuickPickStub.onSecondCall().resolves({label: 'secret-password'}); showQuickPickStub.onThirdCall().resolves({label: 'ConfigMap'}); showQuickPickStub.onCall(3).resolves({label: 'sensitive-recipe-storage'}); - showShowInputBox.onFirstCall().resolves('brownies') - showShowInputBox.onSecondCall().resolves('recipe.txt') + showShowInputBox.onFirstCall().resolves('brownies'); + showShowInputBox.onSecondCall().resolves('recipe.txt'); showQuickPickStub.onCall(4).resolves({label: 'PersistentVolumeClaim'}); - showQuickPickStub.onCall(5).resolves({label: '$(plus) Add new workspace name.'}); - showShowInputBox.onThirdCall().resolves({label: 'shared-task-storage'}); - showShowInputBox.onCall(3).resolves({label: 'path'}); + showQuickPickStub.onCall(5).resolves({label: 'shared-task-storage'}); + showShowInputBox.onThirdCall().resolves('path'); + showQuickPickStub.onCall(6).resolves({label: 'EmptyDir'}); const result = await PipelineContent.startObject(workspace, 'pipeline'); expect(result).deep.equals({ name: 'fetch-and-print-recipe', @@ -245,7 +263,6 @@ suite('PipelineContent', () => { serviceAccount: undefined, workspaces: [ { - emptyDir: undefined, key: undefined, name: 'password-vault', subPath: undefined, @@ -254,7 +271,6 @@ suite('PipelineContent', () => { workspaceType: 'Secret' }, { - emptyDir:undefined, key: 'brownies', name: 'recipe-store', subPath: undefined, @@ -263,20 +279,45 @@ suite('PipelineContent', () => { workspaceType: 'ConfigMap' }, { - emptyDir: undefined, key: undefined, name: 'shared-data', - subPath: { - label: 'path' - }, + subPath: 'path', value: undefined, workspaceName: 'shared-task-storage', workspaceType: 'PersistentVolumeClaim' + }, + { + key: undefined, + name: 'test', + subPath: undefined, + value: undefined, + workspaceName: undefined, + workspaceType: 'EmptyDir' } ] }); }); + test('return error if input is wrong', async () => { + const result = await PipelineContent.validateInput('s@'); + expect(result).equals('invalid'); + }); + + test('return undefined if input is correct', async () => { + const result = await PipelineContent.validateInput('text'); + expect(result).equals(undefined); + }); + + test('return invalid if input text is wrong', async () => { + const result = await PipelineContent.validateTextAndFileName('s@'); + expect(result).equals('invalid'); + }); + + test('return undefined if input text is valid', async () => { + const result = await PipelineContent.validateTextAndFileName('path'); + expect(result).equals(undefined); + }); + test('returns service to start pipeline', async () => { showQuickPickStub.onFirstCall().resolves({label: 'service'}); const result = await PipelineContent.startObject(serviceTrigger, 'pipeline');