techdocs-node: inline swift sdk mock

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2022-03-12 18:26:37 +01:00
parent d25346be78
commit f81513197b
2 changed files with 98 additions and 109 deletions
@@ -1,103 +0,0 @@
/*
* Copyright 2020 The Backstage 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 fs from 'fs-extra';
import os from 'os';
import path from 'path';
import {
ContainerMetaResponse,
DownloadResponse,
NotFound,
ObjectMetaResponse,
UploadResponse,
} from '@trendyol-js/openstack-swift-sdk';
import { Stream, Readable } from 'stream';
const rootDir = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';
const checkFileExists = async (Key: string): Promise<boolean> => {
// Key will always have / as file separator irrespective of OS since cloud providers expects /.
// Normalize Key to OS specific path before checking if file exists.
const filePath = path.join(rootDir, Key);
try {
await fs.access(filePath, fs.constants.F_OK);
return true;
} catch (err) {
return false;
}
};
const streamToBuffer = (stream: Stream | Readable): Promise<Buffer> => {
return new Promise((resolve, reject) => {
try {
const chunks: any[] = [];
stream.on('data', chunk => chunks.push(chunk));
stream.on('error', reject);
stream.on('end', () => resolve(Buffer.concat(chunks)));
} catch (e) {
throw new Error(`Unable to parse the response data ${e.message}`);
}
});
};
export class SwiftClient {
async getMetadata(_containerName: string, file: string) {
const fileExists = await checkFileExists(file);
if (fileExists) {
return new ObjectMetaResponse({
fullPath: file,
});
}
return new NotFound();
}
async getContainerMetadata(containerName: string) {
if (containerName === 'mock') {
return new ContainerMetaResponse({
size: 10,
});
}
return new NotFound();
}
async upload(_containerName: string, destination: string, stream: Readable) {
try {
const filePath = path.join(rootDir, destination);
const fileBuffer = await streamToBuffer(stream);
await fs.writeFile(filePath, fileBuffer);
const fileExists = await checkFileExists(destination);
if (fileExists) {
return new UploadResponse(filePath);
}
const errorMessage = `Unable to upload file(s) to OpenStack Swift.`;
throw new Error(errorMessage);
} catch (error) {
const errorMessage = `Unable to upload file(s) to OpenStack Swift. ${error}`;
throw new Error(errorMessage);
}
}
async download(_containerName: string, file: string) {
const filePath = path.join(rootDir, file);
const fileExists = await checkFileExists(file);
if (!fileExists) {
return new NotFound();
}
return new DownloadResponse([], fs.createReadStream(filePath));
}
}
@@ -24,12 +24,106 @@ import { ConfigReader } from '@backstage/config';
import express from 'express';
import request from 'supertest';
import mockFs from 'mock-fs';
import os from 'os';
import fs from 'fs-extra';
import path from 'path';
import { OpenStackSwiftPublish } from './openStackSwift';
import { PublisherBase, TechDocsMetadata } from './types';
import { storageRootDir } from '../../testUtils/StorageFilesMock';
import { Stream, Readable } from 'stream';
// NOTE: /plugins/techdocs-node/__mocks__ is being used to mock @trendyol-js/openstack-swift-sdk client library
jest.mock('@trendyol-js/openstack-swift-sdk', () => {
const {
ContainerMetaResponse,
DownloadResponse,
NotFound,
ObjectMetaResponse,
UploadResponse,
}: typeof import('@trendyol-js/openstack-swift-sdk') = jest.requireActual(
'@trendyol-js/openstack-swift-sdk',
);
const checkFileExists = async (Key: string): Promise<boolean> => {
// Key will always have / as file separator irrespective of OS since cloud providers expects /.
// Normalize Key to OS specific path before checking if file exists.
const filePath = path.join(storageRootDir, Key);
try {
await fs.access(filePath, fs.constants.F_OK);
return true;
} catch (err) {
return false;
}
};
const streamToBuffer = (stream: Stream | Readable): Promise<Buffer> => {
return new Promise((resolve, reject) => {
try {
const chunks: any[] = [];
stream.on('data', chunk => chunks.push(chunk));
stream.on('error', reject);
stream.on('end', () => resolve(Buffer.concat(chunks)));
} catch (e) {
throw new Error(`Unable to parse the response data ${e.message}`);
}
});
};
return {
__esModule: true,
SwiftClient: class {
async getMetadata(_containerName: string, file: string) {
const fileExists = await checkFileExists(file);
if (fileExists) {
return new ObjectMetaResponse({
fullPath: file,
});
}
return new NotFound();
}
async getContainerMetadata(containerName: string) {
if (containerName === 'mock') {
return new ContainerMetaResponse({
size: 10,
});
}
return new NotFound();
}
async upload(
_containerName: string,
destination: string,
stream: Readable,
) {
try {
const filePath = path.join(storageRootDir, destination);
const fileBuffer = await streamToBuffer(stream);
await fs.writeFile(filePath, fileBuffer);
const fileExists = await checkFileExists(destination);
if (fileExists) {
return new UploadResponse(filePath);
}
const errorMessage = `Unable to upload file(s) to OpenStack Swift.`;
throw new Error(errorMessage);
} catch (error) {
const errorMessage = `Unable to upload file(s) to OpenStack Swift. ${error}`;
throw new Error(errorMessage);
}
}
async download(_containerName: string, file: string) {
const filePath = path.join(storageRootDir, file);
const fileExists = await checkFileExists(file);
if (!fileExists) {
return new NotFound();
}
return new DownloadResponse([], fs.createReadStream(filePath));
}
},
};
});
const createMockEntity = (annotations = {}): Entity => {
return {
@@ -51,15 +145,13 @@ const createMockEntityName = (): CompoundEntityRef => ({
namespace: 'test-namespace',
});
const rootDir = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir';
const getEntityRootDir = (entity: Entity) => {
const {
kind,
metadata: { namespace, name },
} = entity;
return path.join(rootDir, namespace || DEFAULT_NAMESPACE, kind, name);
return path.join(storageRootDir, namespace || DEFAULT_NAMESPACE, kind, name);
};
const getPosixEntityRootDir = (entity: Entity) => {
@@ -179,7 +271,7 @@ describe('OpenStackSwiftPublish', () => {
it('should fail to publish a directory', async () => {
const wrongPathToGeneratedDirectory = path.join(
rootDir,
storageRootDir,
'wrong',
'path',
'to',