Skip to content

Commit

Permalink
[Fleet][EPM] Move SO work from getFileHandler to service method (#85594)
Browse files Browse the repository at this point in the history
## Summary

 - Move registry URL details from handler to Registry service 
 - rename `archive/save_to_es` to `archive/storage` to better reflect its role
 - Move SO handling from http into new  `getAsset` method in `archive/storage`
 - Rearrange code in HTTP handler to be more easily moved to one or two service method(s) which deal with the logic for getting the asset.


### Checklist

- [ ] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios
  • Loading branch information
John Schulz authored Dec 10, 2020
1 parent 008a420 commit 1c36ab9
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 24 deletions.
46 changes: 25 additions & 21 deletions x-pack/plugins/fleet/server/routes/epm/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
BulkInstallPackageInfo,
BulkInstallPackagesResponse,
IBulkInstallPackageHTTPError,
ASSETS_SAVED_OBJECT_TYPE,
} from '../../../common';
import {
GetCategoriesRequestSchema,
Expand Down Expand Up @@ -48,7 +47,7 @@ import { defaultIngestErrorHandler, ingestErrorToResponseOptions } from '../../e
import { splitPkgKey } from '../../services/epm/registry';
import { licenseService } from '../../services';
import { getArchiveEntry } from '../../services/epm/archive/cache';
import { PackageAsset, assetPathToObjectId } from '../../services/epm/archive/save_to_es';
import { getAsset } from '../../services/epm/archive/storage';

export const getCategoriesHandler: RequestHandler<
undefined,
Expand Down Expand Up @@ -113,45 +112,50 @@ export const getFileHandler: RequestHandler<TypeOf<typeof GetFileRequestSchema.p
const useLocalFile = pkgVersion === installation?.version;

if (useLocalFile) {
const archiveKey = `${pkgName}-${pkgVersion}/${filePath}`;
const archiveEntry = getArchiveEntry(archiveKey);
const assetSavedObject = await savedObjectsClient.get<PackageAsset>(
ASSETS_SAVED_OBJECT_TYPE,
assetPathToObjectId(archiveKey)
);
const assetPath = `${pkgName}-${pkgVersion}/${filePath}`;
const fileBuffer = getArchiveEntry(assetPath);
// only pull local installation if we don't have it cached
const storedAsset = !fileBuffer && (await getAsset({ savedObjectsClient, path: assetPath }));

if (!archiveEntry && !assetSavedObject) {
// error, if neither is available
if (!fileBuffer && !storedAsset) {
return response.custom({
body: `installed package file not found: ${filePath}`,
statusCode: 404,
});
}

const headerContentType =
assetSavedObject.attributes.media_type || mime.contentType(path.extname(archiveKey));
if (!headerContentType) {
// if storedAsset is not available, fileBuffer *must* be
// b/c we error if we don't have at least one, and storedAsset is the least likely
const { buffer, contentType } = storedAsset
? {
contentType: storedAsset.media_type,
buffer: storedAsset.data_utf8
? Buffer.from(storedAsset.data_utf8, 'utf8')
: Buffer.from(storedAsset.data_base64, 'base64'),
}
: {
contentType: mime.contentType(path.extname(assetPath)),
buffer: fileBuffer,
};

if (!contentType) {
return response.custom({
body: `unknown content type for file: ${filePath}`,
statusCode: 400,
});
}

const { data_base64: base64, data_utf8: utf8 } = assetSavedObject.attributes;
// if we have a local Buffer, use that
// else, create one from the saved object (try utf8 first)
const responseBody =
archiveEntry || utf8 ? Buffer.from(utf8, 'utf8') : Buffer.from(base64, 'base64');

return response.custom({
body: responseBody,
body: buffer,
statusCode: 200,
headers: {
'cache-control': 'max-age=10, public',
'content-type': headerContentType,
'content-type': contentType,
},
});
} else {
const registryResponse = await getFile(`/package/${pkgName}/${pkgVersion}/${filePath}`);
const registryResponse = await getFile(pkgName, pkgVersion, filePath);
const headersToProxy: KnownHeaders[] = ['content-type', 'cache-control'];
const proxiedHeaders = headersToProxy.reduce((headers, knownHeader) => {
const value = registryResponse.headers.get(knownHeader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,20 @@ export async function archiveEntryToBulkCreateObject(opts: {
attributes: doc,
};
}

export async function getAsset(opts: {
savedObjectsClient: SavedObjectsClientContract;
path: string;
}) {
const { savedObjectsClient, path } = opts;
const assetSavedObject = await savedObjectsClient.get<PackageAsset>(
ASSETS_SAVED_OBJECT_TYPE,
assetPathToObjectId(path)
);
const storedAsset = assetSavedObject?.attributes;
if (!storedAsset) {
return;
}

return storedAsset;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { updateCurrentWriteIndices } from '../elasticsearch/template/template';
import { deleteKibanaSavedObjectsAssets } from './remove';
import { installTransform } from '../elasticsearch/transform/install';
import { createInstallation, saveKibanaAssetsRefs, updateVersion } from './install';
import { saveArchiveEntries } from '../archive/save_to_es';
import { saveArchiveEntries } from '../archive/storage';

// this is only exported for testing
// use a leading underscore to indicate it's not the supported path
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/fleet/server/services/epm/packages/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import * as Registry from '../registry';
import { createInstallableFrom, isRequiredPackage } from './index';
import { getArchivePackage } from '../archive';

export { fetchFile as getFile, SearchParams } from '../registry';
export { getFile, SearchParams } from '../registry';

function nameAsTitle(name: string) {
return name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { deleteTransforms } from '../elasticsearch/transform/remove';
import { packagePolicyService, appContextService } from '../..';
import { splitPkgKey } from '../registry';
import { deletePackageCache } from '../archive';
import { removeArchiveEntries } from '../archive/save_to_es';
import { removeArchiveEntries } from '../archive/storage';

export async function removeInstallation(options: {
savedObjectsClient: SavedObjectsClientContract;
Expand Down
9 changes: 9 additions & 0 deletions x-pack/plugins/fleet/server/services/epm/registry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ export async function fetchInfo(pkgName: string, pkgVersion: string): Promise<Re
return fetchUrl(`${registryUrl}/package/${pkgName}/${pkgVersion}`).then(JSON.parse);
}

export async function getFile(
pkgName: string,
pkgVersion: string,
relPath: string
): Promise<Response> {
const filePath = `/package/${pkgName}/${pkgVersion}/${relPath}`;
return fetchFile(filePath);
}

export async function fetchFile(filePath: string): Promise<Response> {
const registryUrl = getRegistryUrl();
return getResponse(`${registryUrl}${filePath}`);
Expand Down

0 comments on commit 1c36ab9

Please sign in to comment.