Skip to content

Commit

Permalink
handle inline taskSpec in pipeline detail page
Browse files Browse the repository at this point in the history
  • Loading branch information
karthik committed Sep 14, 2020
1 parent e7565ea commit fa864a9
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 21 deletions.
@@ -1,6 +1,7 @@
import * as React from 'react';
import { Alert } from '@patternfly/react-core';
import { Pipeline, PipelineRun } from '../../../../utils/pipeline-augment';
import { hasInlineTaskSpec } from '../../../../utils/pipeline-utils';
import PipelineTopologyGraph from '../../pipeline-topology/PipelineTopologyGraph';
import { getTopologyNodesEdges } from '../../pipeline-topology/utils';
import { PipelineLayout } from '../../pipeline-topology/const';
Expand All @@ -17,21 +18,32 @@ const PipelineVisualization: React.FC<PipelineTopologyVisualizationProps> = ({
pipelineRun,
}) => {
const { nodes, edges } = getTopologyNodesEdges(pipeline, pipelineRun);

if (nodes.length === 0 && edges.length === 0) {
let hasErrors;
if (hasInlineTaskSpec(pipeline)) {
// TODO: Inline taskSpec is not yet supported feature
hasErrors = (
<Alert
variant="info"
isInline
title="This Pipeline cannot be visualized. Pipeline taskSpec is not supported."
/>
);
} else if (nodes.length === 0 && edges.length === 0) {
// Nothing to render
// TODO: Confirm wording with UX; ODC-1860
return <Alert variant="info" isInline title="This Pipeline has no tasks to visualize." />;
hasErrors = <Alert variant="info" isInline title="This Pipeline has no tasks to visualize." />;
}

return (
<div className="odc-pipeline-visualization">
<PipelineTopologyGraph
id={pipelineRun?.metadata?.name || pipeline.metadata.name}
nodes={nodes}
edges={edges}
layout={PipelineLayout.DAGRE_VIEWER}
/>
{hasErrors || (
<PipelineTopologyGraph
id={pipelineRun?.metadata?.name || pipeline.metadata.name}
nodes={nodes}
edges={edges}
layout={PipelineLayout.DAGRE_VIEWER}
/>
)}
</div>
);
};
Expand Down
Expand Up @@ -5,7 +5,7 @@ import { Link } from 'react-router-dom';
import { Tooltip } from '@patternfly/react-core';
import { K8sResourceKind, referenceForModel } from '@console/internal/module/k8s';
import { Firehose, resourcePathFromModel } from '@console/internal/components/utils';
import { runStatus } from '../../../../utils/pipeline-augment';
import { runStatus, PipelineTaskSpec, PipelineTaskRef } from '../../../../utils/pipeline-augment';
import { PipelineRunModel, TaskModel, ClusterTaskModel } from '../../../../models';
import { ColoredStatusIcon } from './StatusIcon';
import { PipelineVisualizationStepList } from './PipelineVisualizationStepList';
Expand Down Expand Up @@ -33,10 +33,8 @@ interface PipelineVisualizationTaskProp {
namespace: string;
task: {
name?: string;
taskRef: {
name: string;
kind?: string;
};
taskSpec?: PipelineTaskSpec;
taskRef?: PipelineTaskRef;
status?: TaskStatus;
};
taskRun?: string;
Expand Down
@@ -0,0 +1,35 @@
import * as React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { Alert } from '@patternfly/react-core';
import { mockPipelinesJSON } from '../../../../../utils/__tests__/pipeline-test-data';
import PipelineTopologyGraph from '../../../pipeline-topology/PipelineTopologyGraph';
import PipelineVisualization from '../PipelineVisualization';

describe('Pipeline Visualization', () => {
type PipelineVisualizationProps = React.ComponentProps<typeof PipelineVisualization>;
let wrapper: ShallowWrapper<PipelineVisualizationProps>;
beforeEach(() => {
wrapper = shallow(<PipelineVisualization pipeline={mockPipelinesJSON[2]} />);
});

it('Should render a Alert message if the pipeline has inline taskSpec ', () => {
const alert = wrapper.find(Alert);
expect(alert).toHaveLength(1);
expect(alert.props().title).toBe(
'This Pipeline cannot be visualized. Pipeline taskSpec is not supported.',
);
});

it('Should render a Alert message if the pipeline does not have tasks', () => {
wrapper.setProps({ pipeline: { ...mockPipelinesJSON[2], spec: { tasks: [] } } });
const alert = wrapper.find(Alert);
expect(alert).toHaveLength(1);
expect(alert.props().title).toBe('This Pipeline has no tasks to visualize.');
});

it('Should render a pipeline Visualization component', () => {
wrapper.setProps({ pipeline: mockPipelinesJSON[1] });
const PipelineTopologyGraphComponent = wrapper.find(PipelineTopologyGraph);
expect(PipelineTopologyGraphComponent).toHaveLength(1);
});
});
Expand Up @@ -5,8 +5,10 @@ import {
reRunPipelineRun,
startPipeline,
getPipelineKebabActions,
editPipeline,
} from '../pipeline-actions';
import { PipelineRun, Pipeline } from '../pipeline-augment';
import { mockPipelinesJSON } from './pipeline-test-data';

export const actionPipelines: Pipeline[] = [
{
Expand Down Expand Up @@ -112,4 +114,10 @@ describe('getPipelineKebabActions', () => {
'Start Last Run',
);
});
it('expect Edit Pipeline option should be hidden when pipeline has inline taskSpec', () => {
const editPipelineAction = editPipeline(PipelineModel, mockPipelinesJSON[2]);
expect(editPipelineAction.label).toBe('Edit Pipeline');
expect(editPipelineAction.callback).not.toBeNull();
expect(editPipelineAction.hidden).toBeTruthy();
});
});
@@ -1,7 +1,7 @@
import { K8sResourceKind } from '@console/internal/module/k8s';
import { pipelineTestData, PipelineExampleNames, DataState } from '../../test/pipeline-data';
import { Pipeline } from '../pipeline-augment';

export const mockPipelinesJSON: K8sResourceKind[] = [
export const mockPipelinesJSON: Pipeline[] = [
{
apiVersion: 'tekton.dev/v1alpha1',
kind: 'Pipeline',
Expand All @@ -12,7 +12,7 @@ export const mockPipelinesJSON: K8sResourceKind[] = [
params: [
{
name: 'APP_NAME',
type: 'string',
description: 'Application name',
default: 'default-app-name',
},
],
Expand Down Expand Up @@ -236,6 +236,29 @@ export const mockPipelinesJSON: K8sResourceKind[] = [
],
},
},
{
apiVersion: 'tekton.dev/v1beta1',
kind: 'Pipeline',
metadata: {
name: 'devconsole',
},
spec: {
tasks: [
{
name: 'use-secret',
taskSpec: {
steps: [
{
name: 'greet',
image: 'registry.access.redhat.com/ubi8/ubi',
script: ['echo "Hello world!"\n'],
},
],
},
},
],
},
},
];

const specificPipelineData = pipelineTestData[PipelineExampleNames.COMPLEX_PIPELINE];
Expand Down
Expand Up @@ -15,6 +15,7 @@ import {
pipelineRunDuration,
getSecretAnnotations,
calculateRelativeTime,
hasInlineTaskSpec,
} from '../pipeline-utils';
import {
constructPipelineData,
Expand Down Expand Up @@ -155,4 +156,14 @@ describe('pipeline-utils ', () => {
const relativeTime = calculateRelativeTime('2020-05-22T10:57:53Z', '2020-05-22T12:57:57Z');
expect(relativeTime).toBe('about 2 hours');
});

it('expect pipeline with inline task spec to return true', () => {
const hasSpec = hasInlineTaskSpec(mockPipelinesJSON[2]);
expect(hasSpec).toBe(true);
});

it('expect pipeline without inline task spec to return false', () => {
const hasSpec = hasInlineTaskSpec(mockPipelinesJSON[0]);
expect(hasSpec).toBe(false);
});
});
2 changes: 2 additions & 0 deletions frontend/packages/dev-console/src/utils/pipeline-actions.tsx
Expand Up @@ -17,6 +17,7 @@ import { StartedByLabel } from '../components/pipelines/const';
import { EventListenerModel, PipelineModel, PipelineRunModel } from '../models';
import { Pipeline, PipelineRun } from './pipeline-augment';
import { pipelineRunFilterReducer } from './pipeline-filter-reducer';
import { hasInlineTaskSpec } from './pipeline-utils';

export const handlePipelineRunSubmit = (pipelineRun: PipelineRun) => {
history.push(
Expand Down Expand Up @@ -59,6 +60,7 @@ export const reRunPipelineRun: KebabAction = (kind: K8sKind, pipelineRun: Pipeli

export const editPipeline: KebabAction = (kind: K8sKind, pipeline: Pipeline) => ({
label: 'Edit Pipeline',
hidden: hasInlineTaskSpec(pipeline),
callback: () => {
const {
metadata: { name, namespace },
Expand Down
12 changes: 11 additions & 1 deletion frontend/packages/dev-console/src/utils/pipeline-augment.ts
Expand Up @@ -45,6 +45,15 @@ export interface PipelineTaskRef {
name: string;
}

export interface PipelineTaskSpec {
steps: {
name: string;
image?: string;
args?: string[];
script?: string[];
}[];
}

export interface PipelineTaskParam {
name: string;
value: any;
Expand All @@ -61,7 +70,8 @@ export interface PipelineTaskResource {
export interface PipelineTask {
name: string;
runAfter?: string[];
taskRef: PipelineTaskRef;
taskRef?: PipelineTaskRef;
taskSpec?: PipelineTaskSpec;
params?: PipelineTaskParam[];
resources?: PipelineTaskResources;
}
Expand Down
9 changes: 6 additions & 3 deletions frontend/packages/dev-console/src/utils/pipeline-utils.ts
Expand Up @@ -64,7 +64,7 @@ export interface PipelineVisualizationTaskItem {
resources?: Resources;
params?: object;
runAfter?: string[];
taskRef: PipelineTaskRef;
taskRef?: PipelineTaskRef;
}

export const TaskStatusClassNameMap = {
Expand Down Expand Up @@ -181,7 +181,10 @@ const appendPipelineRunStatus = (pipeline, pipelineRun) => {
return mTask;
});
};

export const hasInlineTaskSpec = (pipeline: K8sResourceKind) => {
const tasks = pipeline?.spec.tasks ?? [];
return tasks.some((task) => !!(task.taskSpec && !task.taskRef));
};
export const getPipelineTasks = (
pipeline: K8sResourceKind,
pipelineRun: K8sResourceKind = {
Expand All @@ -192,7 +195,7 @@ export const getPipelineTasks = (
): PipelineVisualizationTaskItem[][] => {
// Each unit in 'out' array is termed as stage | out = [stage1 = [task1], stage2 = [task2,task3], stage3 = [task4]]
const out = [];
if (!pipeline.spec || !pipeline.spec.tasks) {
if (!pipeline?.spec.tasks) {
return out;
}
const taskList = appendPipelineRunStatus(pipeline, pipelineRun);
Expand Down

0 comments on commit fa864a9

Please sign in to comment.