pipelines/frontend/server/utils.test.ts

209 lines
6.6 KiB
TypeScript

// Copyright 2020 The Kubeflow Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { PassThrough } from 'stream';
import { PreviewStream, findFileOnPodVolume, resolveFilePathOnVolume } from './utils';
describe('utils', () => {
describe('PreviewStream', () => {
it('should stream first 5 bytes', done => {
const peek = 5;
const input = 'some string that will be truncated.';
const source = new PassThrough();
const preview = new PreviewStream({ peek });
const dst = source.pipe(preview).on('end', done);
source.end(input);
dst.once('readable', () => expect(dst.read().toString()).toBe(input.slice(0, peek)));
});
it('should stream everything if peek==0', done => {
const peek = 0;
const input = 'some string that will be truncated.';
const source = new PassThrough();
const preview = new PreviewStream({ peek });
const dst = source.pipe(preview).on('end', done);
source.end(input);
dst.once('readable', () => expect(dst.read().toString()).toBe(input));
});
});
describe('findFileOnPodVolume', () => {
const podTemplateSpec = {
spec: {
containers: [
{
volumeMounts: [
{
name: 'output',
mountPath: '/main',
},
{
name: 'artifact',
subPath: 'pipeline1',
mountPath: '/main1',
},
{
name: 'artifact',
subPath: 'pipeline2',
mountPath: '/main2',
},
],
name: 'main',
},
{
volumeMounts: [
{
name: 'output',
mountPath: '/data',
},
{
name: 'artifact',
subPath: 'pipeline1',
mountPath: '/data1',
},
{
name: 'artifact',
subPath: 'pipeline2',
mountPath: '/data2',
},
],
name: 'ml-pipeline-ui',
},
],
volumes: [
{
name: 'output',
hostPath: {
path: '/data/output',
type: 'Directory',
},
},
{
name: 'artifact',
persistentVolumeClaim: {
claimName: 'artifact_pvc',
},
},
],
},
};
it('parse file path with containerNames', () => {
const [filePath, err] = findFileOnPodVolume(podTemplateSpec, {
containerNames: ['ml-pipeline-ui', 'ml-pipeline-ui-artifact'],
volumeMountName: 'output',
filePathInVolume: 'a/b/c',
});
expect(err).toEqual(undefined);
expect(filePath).toEqual('/data/a/b/c');
});
it('parse file path with containerNames and subPath', () => {
const [filePath, err] = findFileOnPodVolume(podTemplateSpec, {
containerNames: ['ml-pipeline-ui', 'ml-pipeline-ui-artifact'],
volumeMountName: 'artifact',
filePathInVolume: 'pipeline1/a/b/c',
});
expect(err).toEqual(undefined);
expect(filePath).toEqual('/data1/a/b/c');
});
it('parse file path without containerNames', () => {
const [filePath, err] = findFileOnPodVolume(podTemplateSpec, {
containerNames: undefined,
volumeMountName: 'output',
filePathInVolume: 'a/b/c',
});
expect(err).toEqual(undefined);
expect(filePath).toEqual('/main/a/b/c');
});
it('parse file path error with not exist volume', () => {
const [filePath, err] = findFileOnPodVolume(podTemplateSpec, {
containerNames: undefined,
volumeMountName: 'other',
filePathInVolume: 'a/b/c',
});
expect(err).toEqual(
'Cannot find file "volume://other/a/b/c" in pod "unknown": volume "other" not configured',
);
expect(filePath).toEqual('');
});
it('parse file path error with not exist container', () => {
const [filePath, err] = findFileOnPodVolume(podTemplateSpec, {
containerNames: ['other1', 'other2'],
volumeMountName: 'output',
filePathInVolume: 'a/b/c',
});
expect(err).toEqual(
'Cannot find file "volume://output/a/b/c" in pod "unknown": container "other1" or "other2" not found',
);
expect(filePath).toEqual('');
});
it('parse file path error with volume not mount error', () => {
const [filePath, err] = findFileOnPodVolume(podTemplateSpec, {
containerNames: undefined,
volumeMountName: 'artifact',
filePathInVolume: 'a/b/c',
});
expect(err).toEqual(
'Cannot find file "volume://artifact/a/b/c" in pod "unknown": volume "artifact" not mounted or volume "artifact" with subPath (which is prefix of a/b/c) not mounted',
);
expect(filePath).toEqual('');
});
});
describe('resolveFilePathOnVolume', () => {
it('undefined volumeMountSubPath', () => {
const path = resolveFilePathOnVolume({
filePathInVolume: 'a/b/c',
volumeMountPath: '/data',
volumeMountSubPath: undefined,
});
expect(path).toEqual(['/data/a/b/c', undefined]);
});
it('with volumeMountSubPath', () => {
const path = resolveFilePathOnVolume({
volumeMountPath: '/data',
filePathInVolume: 'a/b/c',
volumeMountSubPath: 'a',
});
expect(path).toEqual(['/data/b/c', undefined]);
});
it('with multiple layer volumeMountSubPath', () => {
const path = resolveFilePathOnVolume({
volumeMountPath: '/data',
filePathInVolume: 'a/b/c',
volumeMountSubPath: 'a/b',
});
expect(path).toEqual(['/data/c', undefined]);
});
it('with not exist volumeMountSubPath', () => {
const path = resolveFilePathOnVolume({
volumeMountPath: '/data',
filePathInVolume: 'a/b/c',
volumeMountSubPath: 'other',
});
expect(path).toEqual([
'',
'File a/b/c not mounted, expecting the file to be inside volume mount subpath other',
]);
});
});
});