Skip to content

Commit

Permalink
Add YAML mode for Create TaskRun
Browse files Browse the repository at this point in the history
Similar to Create PipelineRun, add a button to the Create TaskRun
page allowing the user to switch to YAML mode for more advanced
use cases not currently supported by the form-based UI.

Also add the 'Edit and run' action on the TaskRuns page allowing
users to create a new TaskRun based on an existing one.
  • Loading branch information
AlanGreene committed Feb 17, 2023
1 parent bba51a4 commit cb0fcfc
Show file tree
Hide file tree
Showing 17 changed files with 484 additions and 48 deletions.
102 changes: 85 additions & 17 deletions src/api/taskRuns.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,73 +76,141 @@ export function cancelTaskRun({ name, namespace }) {
return patch(uri, payload);
}

export function createTaskRun({
export function getTaskRunPayload({
kind,
labels,
namespace,
nodeSelector,
params,
serviceAccount,
taskName,
taskRunName = `${taskName}-run-${Date.now()}`,
taskRunName = `${taskName ? `${taskName}-run` : 'run'}-${Date.now()}`,
serviceAccount,
timeout
}) {
const payload = {
apiVersion: `tekton.dev/${getTektonPipelinesAPIVersion()}`,
kind: 'TaskRun',
metadata: {
name: taskRunName,
namespace,
labels
namespace
},
spec: {
params: [],
taskRef: {
name: taskName,
kind: kind || 'Task'
}
}
};
if (nodeSelector) {
payload.spec.podTemplate = { nodeSelector };
if (labels) {
payload.metadata.labels = labels;
}
if (params) {
payload.spec.params = Object.keys(params).map(name => ({
name,
value: params[name]
}));
}
if (nodeSelector) {
payload.spec.podTemplate = { nodeSelector };
}
if (serviceAccount) {
payload.spec.serviceAccountName = serviceAccount;
}
if (timeout) {
payload.spec.timeout = timeout;
}

return payload;
}

export function createTaskRun({
kind,
labels,
namespace,
nodeSelector,
params,
serviceAccount,
taskName,
taskRunName = `${taskName}-run-${Date.now()}`,
timeout
}) {
const payload = getTaskRunPayload({
kind,
labels,
namespace,
nodeSelector,
params,
serviceAccount,
taskName,
taskRunName,
timeout
});
const uri = getTektonAPI('taskruns', { namespace });
return post(uri, payload).then(({ body }) => body);
}

export function rerunTaskRun(taskRun) {
const { annotations, labels, name, namespace } = taskRun.metadata;
export function createTaskRunRaw({ namespace, payload }) {
const uri = getTektonAPI('taskruns', { namespace });
return post(uri, payload).then(({ body }) => body);
}

export function generateNewTaskRunPayload({ taskRun, rerun }) {
const { annotations, labels, name, namespace, generateName } =
taskRun.metadata;

const payload = deepClone(taskRun);
payload.apiVersion =
payload.apiVersion || `tekton.dev/${getTektonPipelinesAPIVersion()}`;
payload.kind = payload.kind || 'TaskRun';

function getGenerateName() {
if (rerun) {
return getGenerateNamePrefixForRerun(name);
}

return generateName || `${name}-`;
}

payload.metadata = {
annotations,
generateName: getGenerateNamePrefixForRerun(name),
labels: {
...labels,
'dashboard.tekton.dev/rerunOf': name
},
annotations: annotations || {},
generateName: getGenerateName(),
labels: labels || {},
namespace
};
if (rerun) {
payload.metadata.labels['dashboard.tekton.dev/rerunOf'] = name;
}

delete payload.metadata.labels['tekton.dev/task'];
Object.keys(payload.metadata.labels).forEach(label => {
if (label.startsWith('tekton.dev/')) {
delete payload.metadata.labels[label];
}
});

Object.keys(payload.metadata.annotations).forEach(annotation => {
if (annotation.startsWith('tekton.dev/')) {
delete payload.metadata.annotations[annotation];
}
});

delete payload.metadata.annotations[
'kubectl.kubernetes.io/last-applied-configuration'
];
Object.keys(payload.metadata).forEach(
i => payload.metadata[i] === undefined && delete payload.metadata[i]
);

delete payload.status;

delete payload.spec?.status;
return { namespace, payload };
}

export function rerunTaskRun(taskRun) {
const { namespace, payload } = generateNewTaskRunPayload({
taskRun,
rerun: true
});

const uri = getTektonAPI('taskruns', { namespace });
return post(uri, payload).then(({ body }) => body);
Expand Down
210 changes: 209 additions & 1 deletion src/api/taskRuns.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import yaml from 'js-yaml';
import * as API from './taskRuns';
import * as utils from './utils';
import * as comms from './comms';
Expand Down Expand Up @@ -158,6 +159,36 @@ describe('createTaskRun', () => {
});
});

it('createTaskRunRaw', () => {
const taskRunRaw = {
apiVersion: 'tekton.dev/v1beta1',
kind: 'TaskRun',
metadata: { name: 'test-task-run-name', namespace: 'test-namespace' },
spec: {
taskSpec: {
steps: [
{
image: 'busybox',
name: 'echo',
script: '#!/bin/ash\necho "Hello World!"\n'
}
]
}
}
};
jest
.spyOn(comms, 'post')
.mockImplementation((uri, body) => Promise.resolve(body));

return API.createTaskRunRaw({
namespace: 'test-namespace',
payload: taskRunRaw
}).then(() => {
expect(comms.post).toHaveBeenCalled();
expect(comms.post.mock.lastCall[1]).toEqual(taskRunRaw);
});
});

it('deleteTaskRun', () => {
const name = 'foo';
const data = { fake: 'taskRun' };
Expand Down Expand Up @@ -254,7 +285,7 @@ it('rerunTaskRun', () => {
apiVersion: 'tekton.dev/v1beta1',
kind: 'TaskRun',
metadata: {
annotations: undefined,
annotations: {},
generateName: `${originalTaskRun.metadata.name}-r-`,
labels: {
'dashboard.tekton.dev/rerunOf': originalTaskRun.metadata.name
Expand All @@ -269,3 +300,180 @@ it('rerunTaskRun', () => {
expect(comms.post.mock.lastCall[1]).toEqual(rerun);
});
});

describe('generateNewTaskRunPayload', () => {
it('rerun with minimum possible fields', () => {
const taskRun = {
apiVersion: 'tekton.dev/v1beta1',
kind: 'TaskRun',
metadata: {
name: 'test',
namespace: 'test-namespace'
},
spec: {
taskRef: {
name: 'simple'
}
}
};
const { namespace, payload } = API.generateNewTaskRunPayload({
taskRun,
rerun: true
});
const expected = `apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
annotations: {}
generateName: test-r-
labels:
dashboard.tekton.dev/rerunOf: test
namespace: test-namespace
spec:
taskRef:
name: simple
`;
expect(namespace).toEqual('test-namespace');
expect(yaml.dump(payload)).toEqual(expected);
});

it('rerun with all processed fields', () => {
const taskRun = {
apiVersion: 'tekton.dev/v1beta1',
kind: 'TaskRun',
metadata: {
name: 'test',
namespace: 'test-namespace',
annotations: {
keya: 'valuea',
'kubectl.kubernetes.io/last-applied-configuration':
'{"apiVersion": "tekton.dev/v1beta1", "keya": "valuea"}'
},
labels: {
key1: 'valuel',
key2: 'value2',
'tekton.dev/task': 'foo'
},
uid: '111-233-33',
resourceVersion: 'aaaa'
},
spec: {
taskRef: {
name: 'simple'
},
params: [{ name: 'param-1' }, { name: 'param-2' }]
},
status: { startTime: '0' }
};
const { namespace, payload } = API.generateNewTaskRunPayload({
taskRun,
rerun: true
});
const expected = `apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
annotations:
keya: valuea
generateName: test-r-
labels:
key1: valuel
key2: value2
dashboard.tekton.dev/rerunOf: test
namespace: test-namespace
spec:
taskRef:
name: simple
params:
- name: param-1
- name: param-2
`;
expect(namespace).toEqual('test-namespace');
expect(yaml.dump(payload)).toEqual(expected);
});

it('edit with minimum possible fields', () => {
const taskRun = {
apiVersion: 'tekton.dev/v1beta1',
kind: 'TaskRun',
metadata: {
name: 'test',
namespace: 'test-namespace'
},
spec: {
taskRef: {
name: 'simple'
}
}
};
const { namespace, payload } = API.generateNewTaskRunPayload({
taskRun,
rerun: false
});
const expected = `apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
annotations: {}
generateName: test-
labels: {}
namespace: test-namespace
spec:
taskRef:
name: simple
`;
expect(namespace).toEqual('test-namespace');
expect(yaml.dump(payload)).toEqual(expected);
});

it('edit with all processed fields', () => {
const taskRun = {
apiVersion: 'tekton.dev/v1beta1',
kind: 'TaskRun',
metadata: {
annotations: {
keya: 'valuea',
'kubectl.kubernetes.io/last-applied-configuration':
'{"apiVersion": "tekton.dev/v1beta1", "keya": "valuea"}'
},
labels: {
key1: 'valuel',
key2: 'value2',
'tekton.dev/task': 'foo',
'tekton.dev/run': 'bar'
},
name: 'test',
namespace: 'test-namespace',
uid: '111-233-33',
resourceVersion: 'aaaa'
},
spec: {
taskRef: {
name: 'simple'
},
params: [{ name: 'param-1' }, { name: 'param-2' }]
},
status: { startTime: '0' }
};
const { namespace, payload } = API.generateNewTaskRunPayload({
taskRun,
rerun: false
});
const expected = `apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
annotations:
keya: valuea
generateName: test-
labels:
key1: valuel
key2: value2
namespace: test-namespace
spec:
taskRef:
name: simple
params:
- name: param-1
- name: param-2
`;
expect(namespace).toEqual('test-namespace');
expect(yaml.dump(payload)).toEqual(expected);
});
});
Loading

0 comments on commit cb0fcfc

Please sign in to comment.