diff --git a/src/tekton/addtrigger.ts b/src/tekton/addtrigger.ts index 7d2d56d2..eee39279 100644 --- a/src/tekton/addtrigger.ts +++ b/src/tekton/addtrigger.ts @@ -26,6 +26,7 @@ import { telemetryLog, telemetryLogError } from '../telemetry'; import { getStderrString } from '../util/stderrstring'; import { VCT } from './pipelinecontent'; import { Command } from '../cli-command'; +import semver = require('semver'); export const TriggerTemplateModel = { apiGroup: 'triggers.tekton.dev', @@ -272,6 +273,7 @@ export function apiVersionForModel(model: K8sKind): string { export async function createEventListener(triggerBindings: TriggerBindingKind[], triggerTemplate: TriggerTemplateKind): Promise { const getNewELSupport: TknVersion = await version(); + const compareVersion = semver.satisfies('0.5.0', `>=${getNewELSupport.trigger}`); return { apiVersion: apiVersionForModel(EventListenerModel), kind: EventListenerModel.kind, @@ -283,14 +285,14 @@ export async function createEventListener(triggerBindings: TriggerBindingKind[], triggers: [ { bindings: triggerBindings.map(({ kind, metadata: { name } }) => { - if ('0.5.0' >= getNewELSupport.trigger) { + if (compareVersion) { return ({ kind, name }); } else { const Ref = name; return ({ kind, Ref }); } }), - template: { name: triggerTemplate.metadata.name }, + template: compareVersion ? { name: triggerTemplate.metadata.name } : { ref: triggerTemplate.metadata.name }, }, ], }, diff --git a/src/util/watchResources.ts b/src/util/watchResources.ts index 3e1b36d5..45d40861 100644 --- a/src/util/watchResources.ts +++ b/src/util/watchResources.ts @@ -73,7 +73,7 @@ export class WatchResources { if (run.status.conditions[0].status === 'True') { window.showInformationMessage(`PipelineRun: ${run.metadata.name} is successfully completed. Duration to complete the execution 'Time: ${humanizer(Date.parse(run.status.completionTime) - Date.parse(run.status.startTime))}'`); } else if (run.status.conditions[0].status === 'False') { - window.showErrorMessage(`PipelineRun: ${run.metadata.name} fails. Reason: ${run.status.conditions[0].reason} and Message: ${run.status.conditions[0].message}`); + window.showErrorMessage(`PipelineRun: ${run.metadata.name} fails. Reason: ${run.status.conditions?.[0].reason} and Message: ${run.status.conditions?.[0].message}`); } } } diff --git a/test/tekton/addtrigger.test.ts b/test/tekton/addtrigger.test.ts index 8a93c81c..192d2581 100644 --- a/test/tekton/addtrigger.test.ts +++ b/test/tekton/addtrigger.test.ts @@ -6,13 +6,19 @@ 'use strict'; +import * as os from 'os'; import * as chai from 'chai'; +import * as fs from 'fs-extra'; import * as sinon from 'sinon'; +import * as yaml from 'js-yaml'; import * as sinonChai from 'sinon-chai'; +import * as _ from 'lodash'; import { TknImpl } from '../../src/tkn'; -import { getPipelineRunFrom, createTriggerTemplate, createEventListener, getPipelineRunWorkspaces } from '../../src/tekton/addtrigger'; +import { getPipelineRunFrom, createTriggerTemplate, createEventListener, getPipelineRunWorkspaces, addTriggerToPipeline, addTrigger } from '../../src/tekton/addtrigger'; import { AddTriggerFormValues, TriggerBindingKind } from '../../src/tekton/triggertype'; import { PipelineRunData, TriggerTemplateKindParam, TriggerTemplateKind } from '../../src/tekton'; +import { cli } from '../../src/cli'; +import { window } from 'vscode'; const expect = chai.expect; @@ -21,38 +27,154 @@ chai.use(sinonChai); suite('Tekton/Pipeline', () => { const sandbox = sinon.createSandbox(); let execStub: sinon.SinonStub; + let cliStub: sinon.SinonStub; + let osStub: sinon.SinonStub; + let writeFileStub: sinon.SinonStub; + let unlinkStub: sinon.SinonStub; + let safeDumpStub: sinon.SinonStub; + let infoMsgStub: sinon.SinonStub; + setup(() => { execStub = sandbox.stub(TknImpl.prototype, 'execute').resolves({ error: null, stdout: '', stderr: '' }); + cliStub = sandbox.stub(cli, 'execute').resolves({ error: null, stdout: '', stderr: '' }); + osStub = sandbox.stub(os, 'tmpdir').returns('path'); + writeFileStub = sandbox.stub(fs, 'writeFile').resolves(); + unlinkStub = sandbox.stub(fs, 'unlink').resolves(); + safeDumpStub = sandbox.stub(yaml, 'safeDump').returns('empty'); + infoMsgStub = sandbox.stub(window, 'showInformationMessage').resolves(); }); teardown(() => { sandbox.restore(); }); - const inputAddTrigger: AddTriggerFormValues = { + const triggerContent = { + name:'vote-app', + resource: { + apiVersion:'triggers.tekton.dev/v1alpha1', + kind:'TriggerBinding', + metadata: { + name:'vote-app', + namespace:'pipelines-tutorial' + }, + spec: { + params: [{ + name:'git-repo-url', + value:'$(body.repository.url)' + }] + } + } + } + + const createTrigger: AddTriggerFormValues = { name:'sample-pipeline-cluster-task-4', - params: [], - resources: [], - workspaces: [], - trigger: { - name:'vote-app', - resource: { - apiVersion:'triggers.tekton.dev/v1alpha1', - kind:'TriggerBinding', + params: [ + { + default: 'gcr.io/christiewilson-catfactory', + name: 'image-registry' + } + ], + resources: [ + { + name: 'source-repo', + resourceRef: 'skaffold-git-multiple-output-image' + } + ], + workspaces: [ + { + name: 'git-source', + workspaceName: 'test', + workspaceType: 'PersistentVolumeClaim' + }, + { + name: 'git-source', + workspaceType: 'EmptyDirectory' + } + ], + volumeClaimTemplate: [ + { + kind: 'volumeClaimTemplate', metadata: { - name:'vote-app', - namespace:'pipelines-tutorial' + name: 'git-source' }, spec: { - params: [{ - name:'git-repo-url', - value:'$(body.repository.url)' - }] + accessModes: ['ReadWriteOnce'], + resources: { + requests: { + storage: '1Mi' + } + } } } + ], + trigger: triggerContent, + serviceAccount: 'default' + } + + const pipeline = { + apiVersion:'tekton.dev/v1beta1', + kind:'Pipeline', + metadata: { + name:'sample-pipeline-cluster-task-4', + namespace:'pipelines-tutorial', + resourceVersion:'34655', + selfLink:'/apis/tekton.dev/v1beta1/namespaces/pipelines-tutorial/pipelines/sample-pipeline-cluster-task-4', + uid:'b2e31019-dece-4201-b8b5-e29b627da0aa' + }, + spec: { + tasks: [{ + name:'cluster-task-pipeline-4', + taskRef: { + kind:'ClusterTask', + name:'cluster-task-pipeline-4' + } + }] } } + + const eventListener = { + apiVersion:'triggers.tekton.dev/v1alpha1', + kind:'EventListener', + metadata: { + name:'event-listener-' + }, + spec: { + serviceAccountName:'pipeline', + triggers: [{ + bindings: [{ + kind:'TriggerBinding', + name:'vote-app' + }], + template: { + name:'trigger-template-sample-pipeline-cluster-task-4-z0we6m' + } + }] + } + } + + const serviceResource = { + spec: { + ports: [ + { + name: 'http-listener', + port: 8080, + protocol: 'TCP', + targetPort: 8000 + } + ] + } + } + + const tknVersion = 'Client version: 0.12.1\nPipeline version: v0.16.3\nTriggers version: v0.5.0\n'; + + const inputAddTrigger: AddTriggerFormValues = { + name:'sample-pipeline-cluster-task-4', + params: [], + resources: [], + workspaces: [], + trigger: triggerContent + } const option: { generateName: boolean } = { generateName: true } @@ -175,26 +297,7 @@ suite('Tekton/Pipeline', () => { }) test('create object for pipelineRun', async () => { - execStub.onFirstCall().resolves({ error: null, stdout: JSON.stringify({ - apiVersion:'tekton.dev/v1beta1', - kind:'Pipeline', - metadata: { - name:'sample-pipeline-cluster-task-4', - namespace:'pipelines-tutorial', - resourceVersion:'34655', - selfLink:'/apis/tekton.dev/v1beta1/namespaces/pipelines-tutorial/pipelines/sample-pipeline-cluster-task-4', - uid:'b2e31019-dece-4201-b8b5-e29b627da0aa' - }, - spec: { - tasks: [{ - name:'cluster-task-pipeline-4', - taskRef: { - kind:'ClusterTask', - name:'cluster-task-pipeline-4' - } - }] - } - }), stderr: '' }) + execStub.onFirstCall().resolves({ error: null, stdout: JSON.stringify(pipeline), stderr: '' }); const result = await getPipelineRunFrom(inputAddTrigger, option); expect(execStub).called; expect(result).deep.equals({ @@ -255,28 +358,68 @@ suite('Tekton/Pipeline', () => { }); test('create object for EventListener', async () => { - execStub.onFirstCall().resolves({ error: null, stdout: 'Client version: 0.12.1\nPipeline version: v0.16.3\nTriggers version: v0.5.0\n', stderr: '' }); + execStub.onFirstCall().resolves({ error: null, stdout: tknVersion, stderr: '' }); sandbox.stub(Math, 'random').returns(1); const result = await createEventListener(triggerBindings, triggerTemplate); - expect(result).deep.equals({ - apiVersion:'triggers.tekton.dev/v1alpha1', - kind:'EventListener', - metadata: { - name:'event-listener-' - }, - spec: { - serviceAccountName:'pipeline', - triggers: [{ - bindings: [{ - kind:'TriggerBinding', - name:'vote-app' - }], - template: { - name:'trigger-template-sample-pipeline-cluster-task-4-z0we6m' - } - }] - } - }); + expect(result).deep.equals(eventListener); + }); + + test('create trigger', async () => { + execStub.onFirstCall().resolves({ error: null, stdout: JSON.stringify(pipeline), stderr: '' }); + cliStub.onFirstCall().resolves({ error: null, stdout: JSON.stringify({kind: 'TriggerTemplate'}), stderr: '' }); + execStub.onSecondCall().resolves({ error: null, + stdout: tknVersion, + stderr: '' }); + cliStub.onSecondCall().resolves({ error: null, stdout: JSON.stringify({kind: 'EventListener'}), stderr: '' }); + execStub.onThirdCall().resolves({ error: null, + stdout: tknVersion, + stderr: '' }); + execStub.onCall(2).resolves({ error: null, + stdout: JSON.stringify(eventListener), + stderr: '' }); + execStub.onCall(3).resolves({ error: null, + stdout: JSON.stringify(serviceResource), + stderr: '' }); + cliStub.onSecondCall().resolves({ error: null, stdout: 'successful', stderr: '' }); + execStub.onCall(4).resolves({ error: null, + stdout: JSON.stringify({ + spec: { + host: 'el-event-listener-dbpg2j-pipelines-tutorial.apps.dev-svc-4.8-042807.devcluster.openshift.com' + } + }), + stderr: '' }); + sandbox.stub(_, 'get').returns('https'); + await addTriggerToPipeline(createTrigger); + infoMsgStub.calledOnce; + safeDumpStub.calledOnce; + osStub.calledOnce; + writeFileStub.calledOnce; + unlinkStub.calledOnce; + }); + + test('return null if fails to create triggerTemplate', async () => { + execStub.onFirstCall().resolves({ error: null, stdout: JSON.stringify(pipeline), stderr: '' }); + cliStub.onFirstCall().resolves({ error: 'error', stdout: '' }); + const result = await addTrigger(createTrigger); + expect(result).equals(null); + }); + + test('return null if fails to create eventListener', async () => { + execStub.onFirstCall().resolves({ error: null, stdout: JSON.stringify(pipeline), stderr: '' }); + cliStub.onFirstCall().resolves({ error: null, stdout: JSON.stringify({kind: 'TriggerTemplate'}), stderr: '' }); + execStub.onSecondCall().resolves({ error: null, + stdout: tknVersion, + stderr: '' }); + cliStub.onSecondCall().resolves({ error: 'error', stdout: '', stderr: '' }); + const result = await addTrigger(createTrigger); + expect(result).equals(null); + }); + + test('return null if fails to create tempPath', async () => { + execStub.onFirstCall().resolves({ error: null, stdout: JSON.stringify(pipeline), stderr: '' }); + osStub.onFirstCall().returns(null); + const result = await addTrigger(createTrigger); + expect(result).equals(null); }); }); });