Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ingest Manger] Move asset getters out of registry #83214

Merged
merged 2 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion x-pack/plugins/fleet/server/services/epm/archive/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ArchivePackage } from '../../../../common/types';
import { ArchivePackage, AssetParts } from '../../../../common/types';
import { PackageInvalidArchiveError, PackageUnsupportedMediaTypeError } from '../../../errors';
import {
cacheGet,
cacheSet,
cacheDelete,
getArchiveFilelist,
Expand Down Expand Up @@ -100,3 +101,40 @@ export const deletePackageCache = (name: string, version: string) => {
// this has been populated in unpackArchiveToCache()
paths?.forEach((path) => cacheDelete(path));
};

export function getPathParts(path: string): AssetParts {
let dataset;

let [pkgkey, service, type, file] = path.split('/');

// if it's a data stream
if (service === 'data_stream') {
// save the dataset name
dataset = type;
// drop the `data_stream/dataset-name` portion & re-parse
[pkgkey, service, type, file] = path.replace(`data_stream/${dataset}/`, '').split('/');
}

// This is to cover for the fields.yml files inside the "fields" directory
if (file === undefined) {
file = type;
type = 'fields';
service = '';
}

return {
pkgkey,
service,
type,
file,
dataset,
path,
} as AssetParts;
}

export function getAsset(key: string) {
const buffer = cacheGet(key);
if (buffer === undefined) throw new Error(`Cannot find asset ${key}`);

return buffer;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
*/

import { CallESAsCurrentUser, ElasticsearchAssetType } from '../../../../types';
import * as Registry from '../../registry';
import { getAsset, getPathParts } from '../../archive';

export async function installILMPolicy(paths: string[], callCluster: CallESAsCurrentUser) {
const ilmPaths = paths.filter((path) => isILMPolicy(path));
if (!ilmPaths.length) return;
await Promise.all(
ilmPaths.map(async (path) => {
const body = Registry.getAsset(path).toString('utf-8');
const { file } = Registry.pathParts(path);
const body = getAsset(path).toString('utf-8');
const { file } = getPathParts(path);
const name = file.substr(0, file.lastIndexOf('.'));
try {
await callCluster('transport.request', {
Expand All @@ -28,7 +28,7 @@ export async function installILMPolicy(paths: string[], callCluster: CallESAsCur
);
}
const isILMPolicy = (path: string) => {
const pathParts = Registry.pathParts(path);
const pathParts = getPathParts(path);
return pathParts.type === ElasticsearchAssetType.ilmPolicy;
};
export async function policyExists(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
ElasticsearchAssetType,
InstallablePackage,
} from '../../../../types';
import * as Registry from '../../registry';
import { ArchiveEntry } from '../../registry';
import { getAsset, getPathParts } from '../../archive';
import { CallESAsCurrentUser } from '../../../../types';
import { saveInstalledEsRefs } from '../../packages/install';
import { getInstallationObject } from '../../packages';
Expand Down Expand Up @@ -127,7 +128,7 @@ export async function installPipelinesForDataStream({
dataStream,
packageVersion: pkgVersion,
});
const content = Registry.getAsset(path).toString('utf-8');
const content = getAsset(path).toString('utf-8');
pipelines.push({
name,
nameForInstallation,
Expand Down Expand Up @@ -192,10 +193,10 @@ async function installPipeline({
return { id: pipeline.nameForInstallation, type: ElasticsearchAssetType.ingestPipeline };
}

const isDirectory = ({ path }: Registry.ArchiveEntry) => path.endsWith('/');
const isDirectory = ({ path }: ArchiveEntry) => path.endsWith('/');

const isDataStreamPipeline = (path: string, dataStreamDataset: string) => {
const pathParts = Registry.pathParts(path);
const pathParts = getPathParts(path);
return (
!isDirectory({ path }) &&
pathParts.type === ElasticsearchAssetType.ingestPipeline &&
Expand All @@ -204,7 +205,7 @@ const isDataStreamPipeline = (path: string, dataStreamDataset: string) => {
);
};
const isPipeline = (path: string) => {
const pathParts = Registry.pathParts(path);
const pathParts = getPathParts(path);
return pathParts.type === ElasticsearchAssetType.ingestPipeline;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { CallESAsCurrentUser } from '../../../../types';
import { Field, loadFieldsFromYaml, processFields } from '../../fields/field';
import { getPipelineNameForInstallation } from '../ingest_pipeline/install';
import { generateMappings, generateTemplateName, getTemplate } from './template';
import * as Registry from '../../registry';
import { getAsset, getPathParts } from '../../archive';
import { removeAssetsFromInstalledEsByType, saveInstalledEsRefs } from '../../packages/install';

export const installTemplates = async (
Expand Down Expand Up @@ -76,9 +76,9 @@ export const installTemplates = async (
const installPreBuiltTemplates = async (paths: string[], callCluster: CallESAsCurrentUser) => {
const templatePaths = paths.filter((path) => isTemplate(path));
const templateInstallPromises = templatePaths.map(async (path) => {
const { file } = Registry.pathParts(path);
const { file } = getPathParts(path);
const templateName = file.substr(0, file.lastIndexOf('.'));
const content = JSON.parse(Registry.getAsset(path).toString('utf8'));
const content = JSON.parse(getAsset(path).toString('utf8'));
let templateAPIPath = '_template';

// v2 index templates need to be installed through the new API endpoint.
Expand Down Expand Up @@ -121,9 +121,9 @@ const installPreBuiltComponentTemplates = async (
) => {
const templatePaths = paths.filter((path) => isComponentTemplate(path));
const templateInstallPromises = templatePaths.map(async (path) => {
const { file } = Registry.pathParts(path);
const { file } = getPathParts(path);
const templateName = file.substr(0, file.lastIndexOf('.'));
const content = JSON.parse(Registry.getAsset(path).toString('utf8'));
const content = JSON.parse(getAsset(path).toString('utf8'));

const callClusterParams: {
method: string;
Expand Down Expand Up @@ -151,12 +151,12 @@ const installPreBuiltComponentTemplates = async (
};

const isTemplate = (path: string) => {
const pathParts = Registry.pathParts(path);
const pathParts = getPathParts(path);
return pathParts.type === ElasticsearchAssetType.indexTemplate;
};

const isComponentTemplate = (path: string) => {
const pathParts = Registry.pathParts(path);
const pathParts = getPathParts(path);
return pathParts.type === ElasticsearchAssetType.componentTemplate;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/

import * as Registry from '../../registry';

export const getAsset = (path: string): Buffer => {
return Registry.getAsset(path);
};
export { getAsset } from '../../archive';
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { SavedObjectsClientContract } from 'kibana/server';

import { saveInstalledEsRefs } from '../../packages/install';
import * as Registry from '../../registry';
import { getPathParts } from '../../archive';
import {
ElasticsearchAssetType,
EsAssetReference,
Expand Down Expand Up @@ -104,7 +104,7 @@ export const installTransform = async (
};

const isTransform = (path: string) => {
const pathParts = Registry.pathParts(path);
const pathParts = getPathParts(path);
return !path.endsWith('/') && pathParts.type === ElasticsearchAssetType.transform;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
SavedObjectsClientContract,
} from 'src/core/server';
import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../../../common';
import * as Registry from '../../registry';
import { getAsset, getPathParts } from '../../archive';
import {
AssetType,
KibanaAssetType,
Expand Down Expand Up @@ -57,7 +57,7 @@ const AssetInstallers: Record<
};

export async function getKibanaAsset(key: string): Promise<ArchiveAsset> {
const buffer = Registry.getAsset(key);
const buffer = getAsset(key);

// cache values are buffers. convert to string / JSON
return JSON.parse(buffer.toString('utf8'));
Expand Down Expand Up @@ -117,14 +117,14 @@ export async function getKibanaAssets(
): Promise<Record<KibanaAssetType, ArchiveAsset[]>> {
const kibanaAssetTypes = Object.values(KibanaAssetType);
const isKibanaAssetType = (path: string) => {
const parts = Registry.pathParts(path);
const parts = getPathParts(path);

return parts.service === 'kibana' && (kibanaAssetTypes as string[]).includes(parts.type);
};

const filteredPaths = paths
.filter(isKibanaAssetType)
.map<[string, AssetParts]>((path) => [path, Registry.pathParts(path)]);
.map<[string, AssetParts]>((path) => [path, getPathParts(path)]);

const assetArrays: Array<Promise<ArchiveAsset[]>> = [];
for (const assetType of kibanaAssetTypes) {
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/fleet/server/services/epm/packages/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { InstallablePackage } from '../../../types';
import * as Registry from '../registry';
import { getArchiveFilelist } from '../archive/cache';
import { getArchiveFilelist, getAsset } from '../archive';

// paths from RegistryPackage are routes to the assets on EPR
// e.g. `/package/nginx/1.2.0/data_stream/access/fields/fields.yml`
Expand Down Expand Up @@ -59,7 +59,7 @@ export async function getAssetsData(
// Gather all asset data
const assets = getAssets(packageInfo, filter, datasetName);
const entries: Registry.ArchiveEntry[] = assets.map((path) => {
const buffer = Registry.getAsset(path);
const buffer = getAsset(path);

return { path, buffer };
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
*/

import { AssetParts } from '../../../types';
import { getBufferExtractor, pathParts, splitPkgKey } from './index';
import { getPathParts } from '../archive';
import { getBufferExtractor, splitPkgKey } from './index';
import { untarBuffer, unzipBuffer } from './extract';

const testPaths = [
Expand Down Expand Up @@ -46,7 +47,7 @@ const testPaths = [

test('testPathParts', () => {
for (const value of testPaths) {
expect(pathParts(value.path)).toStrictEqual(value.assetParts as AssetParts);
expect(getPathParts(value.path)).toStrictEqual(value.assetParts as AssetParts);
}
});

Expand Down
48 changes: 7 additions & 41 deletions x-pack/plugins/fleet/server/services/epm/registry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import semver from 'semver';
import { Response } from 'node-fetch';
import { URL } from 'url';
import {
AssetParts,
AssetsGroupedByServiceByType,
CategoryId,
CategorySummaryList,
Expand All @@ -18,8 +17,12 @@ import {
RegistrySearchResults,
RegistrySearchResult,
} from '../../../types';
import { unpackArchiveToCache } from '../archive';
import { cacheGet, getArchiveFilelist, setArchiveFilelist } from '../archive';
import {
getArchiveFilelist,
getPathParts,
setArchiveFilelist,
unpackArchiveToCache,
} from '../archive';
import { fetchUrl, getResponse, getResponseStream } from './requests';
import { streamToBuffer } from './streams';
import { getRegistryUrl } from './registry_url';
Expand Down Expand Up @@ -146,36 +149,6 @@ export async function getRegistryPackage(
return { paths, registryPackageInfo };
}

export function pathParts(path: string): AssetParts {
let dataset;

let [pkgkey, service, type, file] = path.split('/');

// if it's a data stream
if (service === 'data_stream') {
// save the dataset name
dataset = type;
// drop the `data_stream/dataset-name` portion & re-parse
[pkgkey, service, type, file] = path.replace(`data_stream/${dataset}/`, '').split('/');
}

// This is to cover for the fields.yml files inside the "fields" directory
if (file === undefined) {
file = type;
type = 'fields';
service = '';
}

return {
pkgkey,
service,
type,
file,
dataset,
path,
} as AssetParts;
}

export async function ensureCachedArchiveInfo(
name: string,
version: string,
Expand Down Expand Up @@ -204,19 +177,12 @@ async function fetchArchiveBuffer(
return { archiveBuffer, archivePath };
}

export function getAsset(key: string) {
const buffer = cacheGet(key);
if (buffer === undefined) throw new Error(`Cannot find asset ${key}`);

return buffer;
}

export function groupPathsByService(paths: string[]): AssetsGroupedByServiceByType {
const kibanaAssetTypes = Object.values<string>(KibanaAssetType);

// ASK: best way, if any, to avoid `any`?
const assets = paths.reduce((map: any, path) => {
const parts = pathParts(path.replace(/^\/package\//, ''));
const parts = getPathParts(path.replace(/^\/package\//, ''));
if (parts.service === 'kibana' && kibanaAssetTypes.includes(parts.type)) {
if (!map[parts.service]) map[parts.service] = {};
if (!map[parts.service][parts.type]) map[parts.service][parts.type] = [];
Expand Down