209 lines
6.6 KiB
TypeScript
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',
|
|
]);
|
|
});
|
|
});
|
|
});
|