chore(frontend): Mock one v2 pipeline spec response. Fix #6232 (#6233)

This commit is contained in:
James Liu 2021-08-05 19:14:49 -07:00 committed by GitHub
parent 25958081e6
commit 78c550ee11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 422 additions and 59 deletions

View File

@ -0,0 +1,4 @@
## V2 mock pipelines specification
This folder is for KFP UI to mock backend response, the files here are copied from
[sdk/python/kfp/v2/compiler_cli_tests/test_data](sdk/python/kfp/v2/compiler_cli_tests/test_data). This folder doesn't need to be in sync with the code source in sdk/python/kfp/v2/compiler_cli_tests/test_data folder, but you can do it manually if there is a need to facilitate frontend development by using newer version of compiled pipeline definition.

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,7 @@
import { ApiExperiment } from '../src/apis/experiment';
import { ApiJob } from '../src/apis/job';
import { ApiPipeline } from '../src/apis/pipeline';
import { ApiPipeline, ApiPipelineVersion } from '../src/apis/pipeline';
import { ApiRelationship, ApiResourceType, ApiRunDetail, RunMetricFormat } from '../src/apis/run';
import helloWorldRun from './hello-world-runtime';
import helloWorldWithStepsRun from './hello-world-with-steps-runtime';
@ -38,58 +38,99 @@ const NUM_DUMMY_PIPELINES = 30;
const NUM_DUMMY_JOBS = 20;
const NUM_DUMMY_RUNS = 20;
const PIPELINE_ID_V2_PYTHON_TWO_STEPS = '8fbe3bd6-a01f-11e8-98d0-529269fb1460';
const PIPELINE_V2_PYTHON_TWO_STEPS_DEFAULT: ApiPipelineVersion = {
created_at: new Date('2021-08-01T20:58:23.000Z'),
id: PIPELINE_ID_V2_PYTHON_TWO_STEPS,
name: 'v2_lightweight_python_functions_pipeline',
parameters: [
{
name: 'message',
},
],
};
const PIPELINE_V2_PYTHON_TWO_STEPS: ApiPipeline = {
description: 'V2 two steps: preprocess and training.',
...PIPELINE_V2_PYTHON_TWO_STEPS_DEFAULT,
default_version: PIPELINE_V2_PYTHON_TWO_STEPS_DEFAULT,
};
const PIPELINE_UNSTRUCTED_TEXT_DEFAULT: ApiPipelineVersion = {
created_at: new Date('2018-04-01T20:58:23.000Z'),
id: '8fbe3bd6-a01f-11e8-98d0-529269fb1459',
name: 'Unstructured text',
parameters: [
{
name: 'x',
},
{
name: 'y',
},
{
name: 'output',
},
],
};
const PIPELINE_UNSTRUCTED_TEXT: ApiPipeline = {
description: 'An unstructured text pipeline.',
...PIPELINE_UNSTRUCTED_TEXT_DEFAULT,
default_version: PIPELINE_UNSTRUCTED_TEXT_DEFAULT,
};
const PIPELINE_IMAGE_CLASSIFICATION_DEFAULT: ApiPipelineVersion = {
created_at: new Date('2018-04-02T20:59:29.000Z'),
id: '8fbe3f78-a01f-11e8-98d0-529269fb1459',
name: 'Image classification',
parameters: [
{
name: 'project',
},
{
name: 'workers',
},
{
name: 'rounds',
},
{
name: 'output',
},
],
};
const PIPELINE_IMAGE_CLASSIFICATION: ApiPipeline = {
description: 'An awesome image classification pipeline.',
...PIPELINE_IMAGE_CLASSIFICATION_DEFAULT,
default_version: PIPELINE_IMAGE_CLASSIFICATION_DEFAULT,
};
const PIPELINE_NO_PARAM_DEFAULT: ApiPipelineVersion = {
created_at: new Date('2018-04-03T20:58:23.000Z'),
id: '8fbe41b2-a01f-11e8-98d0-529269fb1459',
name: 'No parameters',
parameters: [],
};
const PIPELINE_NO_PARAM: ApiPipeline = {
description: 'This pipeline has no parameters',
...PIPELINE_NO_PARAM_DEFAULT,
default_version: PIPELINE_NO_PARAM_DEFAULT,
};
const PIPELINE_UNDEFINED_PARAM_DEFAULT: ApiPipelineVersion = {
created_at: new Date('2018-04-04T20:58:23.000Z'),
id: '8fbe42f2-a01f-11e8-98d0-529269fb1459',
name: 'Undefined parameters',
parameters: undefined as any,
};
const PIPELINE_UNDEFINED_PARAM: ApiPipeline = {
description: 'This pipeline has undefined parameters',
...PIPELINE_UNDEFINED_PARAM_DEFAULT,
default_version: PIPELINE_UNDEFINED_PARAM_DEFAULT,
};
const pipelines: ApiPipeline[] = [
{
created_at: new Date('2018-04-01T20:58:23.000Z'),
description: 'An awesome unstructured text pipeline.',
id: '8fbe3bd6-a01f-11e8-98d0-529269fb1459',
name: 'Unstructured text',
parameters: [
{
name: 'x',
},
{
name: 'y',
},
{
name: 'output',
},
],
},
{
created_at: new Date('2018-04-02T20:59:29.000Z'),
description: 'An awesome image classification pipeline.',
id: '8fbe3f78-a01f-11e8-98d0-529269fb1459',
name: 'Image classification',
parameters: [
{
name: 'project',
},
{
name: 'workers',
},
{
name: 'rounds',
},
{
name: 'output',
},
],
},
{
created_at: new Date('2018-04-03T20:58:23.000Z'),
description: 'This pipeline has no parameters',
id: '8fbe41b2-a01f-11e8-98d0-529269fb1459',
name: 'No parameters',
parameters: [],
},
{
created_at: new Date('2018-04-04T20:58:23.000Z'),
description: 'This pipeline has undefined parameters',
id: '8fbe42f2-a01f-11e8-98d0-529269fb1459',
name: 'Undefined parameters',
parameters: undefined as any,
},
PIPELINE_UNSTRUCTED_TEXT,
PIPELINE_IMAGE_CLASSIFICATION,
PIPELINE_NO_PARAM,
PIPELINE_UNDEFINED_PARAM,
{
created_at: new Date('2018-04-01T20:59:23.000Z'),
description: 'Trying to delete this Pipeline will result in an error.',
@ -122,6 +163,7 @@ const pipelines: ApiPipeline[] = [
name: 'A pipeline with a very very very very very very very long name',
parameters: [],
},
PIPELINE_V2_PYTHON_TWO_STEPS,
];
pipelines.push(...generateNPipelines());
@ -832,9 +874,17 @@ export const data = {
// tslint:disable:object-literal-sort-keys
export const namedPipelines = {
unstructuredTextPipeline: pipelines[0],
imageClassificationPipeline: pipelines[1],
noParamsPipeline: pipelines[2],
undefinedParamsPipeline: pipelines[3],
v2PythonTwoSteps: PIPELINE_V2_PYTHON_TWO_STEPS,
unstructuredText: PIPELINE_UNSTRUCTED_TEXT,
imageClassification: PIPELINE_IMAGE_CLASSIFICATION,
noParams: PIPELINE_NO_PARAM,
undefinedParams: PIPELINE_UNDEFINED_PARAM,
};
// tslint:enable:object-literal-sort-keys
export const v2PipelineSpecMap: Map<string, string> = new Map([
[
PIPELINE_ID_V2_PYTHON_TWO_STEPS,
'./mock-backend/data/v2/pipeline/mock_lightweight_python_functions_v2_pipeline.json',
],
]);

View File

@ -25,7 +25,7 @@ import { ApiListPipelinesResponse, ApiPipeline } from '../src/apis/pipeline';
import { ApiListRunsResponse, ApiResourceType, ApiRun, ApiRunStorageState } from '../src/apis/run';
import { ExperimentSortKeys, PipelineSortKeys, RunSortKeys } from '../src/lib/Apis';
import { Response } from 'express-serve-static-core';
import { data as fixedData, namedPipelines } from './fixed-data';
import { data as fixedData, namedPipelines, v2PipelineSpecMap } from './fixed-data';
const rocMetadataJsonPath = './eval-output/metadata.json';
const rocMetadataJsonPath2 = './eval-output/metadata2.json';
@ -499,16 +499,68 @@ export default (app: express.Application) => {
return;
}
let filePath = '';
if (req.params.pid === namedPipelines.noParamsPipeline.id) {
if (req.params.pid === namedPipelines.noParams.id) {
filePath = './mock-backend/mock-conditional-template.yaml';
} else if (req.params.pid === namedPipelines.unstructuredTextPipeline.id) {
} else if (req.params.pid === namedPipelines.unstructuredText.id) {
filePath = './mock-backend/mock-recursive-template.yaml';
} else {
filePath = './mock-backend/mock-template.yaml';
}
if (v2PipelineSpecMap.has(req.params.pid)) {
const specPath = v2PipelineSpecMap.get(req.params.pid);
if (specPath) {
filePath = specPath;
}
console.log(filePath);
}
res.send(JSON.stringify({ template: fs.readFileSync(filePath, 'utf-8') }));
});
app.get(v1beta1Prefix + '/pipeline_versions', (req, res) => {
// Sample query format:
// query: {
// 'resource_key.type': 'PIPELINE',
// 'resource_key.id': '8fbe3bd6-a01f-11e8-98d0-529269fb1459',
// page_size: '50',
// sort_by: 'created_at desc'
// },
if (
req.query['resource_key.id'] &&
req.query['resource_key.type'] === 'PIPELINE' &&
req.query.page_size > 0
) {
const pipeline = fixedData.pipelines.find(p => p.id === req.query['resource_key.id']);
if (pipeline == null) {
return;
}
const pipeline_versions_list_response: ApiListPipelinesResponse = {
total_size: 1,
pipelines: [pipeline],
};
res.send(JSON.stringify(pipeline_versions_list_response));
}
return;
});
app.get(v1beta1Prefix + '/pipeline_versions/:pid', (req, res) => {
// TODO: Temporary returning default version only. It requires
// keeping a record of all pipeline id in order to search non-default version.
res.header('Content-Type', 'application/json');
const pipeline = fixedData.pipelines.find(p => p.id === req.params.pid);
if (!pipeline) {
res
.status(404)
.send(
`No pipeline found with ID: ${req.params.pid}, non-default version can't be found yet.`,
);
return;
}
if (pipeline.default_version) {
res.json(pipeline.default_version);
}
});
function mockCreatePipeline(res: Response, name: string, body?: any): void {
res.header('Content-Type', 'application/json');
// Don't allow uploading multiple pipelines with the same name