From 362555aaf483687fe645b9798caca63fb1a9294e Mon Sep 17 00:00:00 2001 From: John Schulz Date: Tue, 9 Jul 2019 09:48:11 -0400 Subject: [PATCH 01/11] Split integrations.ts into integrations/{index,handlers}.ts Essentially a mechanical refactor for now. Will work on reducing the work done in the handlers in later commits/PRs. --- .../server/integrations/handlers.ts | 103 ++++++++++++++ .../index.ts} | 127 +++--------------- 2 files changed, 123 insertions(+), 107 deletions(-) create mode 100644 x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts rename x-pack/legacy/plugins/integrations_manager/server/{integrations.ts => integrations/index.ts} (55%) diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts new file mode 100644 index 0000000000000..a125414e2245c --- /dev/null +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SavedObjectsBulkGetObject } from 'src/core/server/saved_objects'; +import { Request, InstallationSavedObject } from '../../common/types'; +import { SAVED_OBJECT_TYPE } from '../../common/constants'; +import { + createInstallationObject, + createIntegrationList, + getInstallationObject, + getObjects, +} from './index'; +import * as Registry from '../registry'; +import { getClient } from '../saved_objects'; + +interface PackageRequest extends Request { + params: { + pkgkey: string; + }; +} + +interface InstallFeatureRequest extends PackageRequest { + params: { + pkgkey: string; + feature: string; + }; +} + +export async function handleGetList(req: Request) { + const registryItems = await Registry.fetchList(); + const searchObjects: SavedObjectsBulkGetObject[] = registryItems.map(({ name, version }) => ({ + type: SAVED_OBJECT_TYPE, + id: `${name}-${version}`, + })); + const client = getClient(req); + const results = await client.bulkGet(searchObjects); + const savedObjects: InstallationSavedObject[] = results.saved_objects.filter(o => !o.error); // ignore errors for now + const integrationList = createIntegrationList(registryItems, savedObjects); + + return integrationList; +} + +export async function handleGetInfo(req: PackageRequest) { + const { pkgkey } = req.params; + const item = await Registry.fetchInfo(pkgkey); + const savedObject = await getInstallationObject(getClient(req), pkgkey); + const installation = createInstallationObject(item, savedObject); + + return installation; +} + +export async function handleRequestInstall(req: InstallFeatureRequest) { + const { pkgkey, feature } = req.params; + + if (feature === 'dashboard') { + const toBeSavedObjects = await getObjects(pkgkey, feature); + const client = getClient(req); + const createResults = await client.bulkCreate(toBeSavedObjects, { overwrite: true }); + const installed = createResults.saved_objects.map(({ id, type }) => ({ id, type })); + const mgrResults = await client.create( + SAVED_OBJECT_TYPE, + { installed }, + { id: pkgkey, overwrite: true } + ); + + return mgrResults; + } + + return { + pkgkey, + feature, + created: [], + }; +} + +export async function handleRequestDelete(req: InstallFeatureRequest) { + const { pkgkey, feature } = req.params; + const client = getClient(req); + + const installation = await getInstallationObject(client, pkgkey); + const installedObjects = (installation && installation.attributes.installed) || []; + + // Delete the manager saved object with references to the asset objects + // could also update with [] or some other state + await client.delete(SAVED_OBJECT_TYPE, pkgkey); + + // ASK: should the manager uninstall the assets it installed + // or just the references in SAVED_OBJECT_TYPE? + if (feature === 'dashboard') { + // Delete the installed assets + const deletePromises = installedObjects.map(async ({ id, type }) => client.delete(type, id)); + await Promise.all(deletePromises); + } + + return { + pkgkey, + feature, + deleted: installedObjects, + }; +} diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/index.ts similarity index 55% rename from x-pack/legacy/plugins/integrations_manager/server/integrations.ts rename to x-pack/legacy/plugins/integrations_manager/server/integrations/index.ts index aeb9dda27d461..392d817d21ce2 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/index.ts @@ -7,118 +7,21 @@ import { SavedObject, SavedObjectReference, - SavedObjectsBulkGetObject, SavedObjectsClientContract, } from 'src/core/server/saved_objects'; -import { SAVED_OBJECT_TYPE } from '../common/constants'; +import { SAVED_OBJECT_TYPE } from '../../common/constants'; import { - Request, InstallationSavedObject, IntegrationInfo, IntegrationListItem, RegistryList, RegistryListItem, RegistryPackage, -} from '../common/types'; -import { cacheGet } from './cache'; -import * as Registry from './registry'; -import { getClient } from './saved_objects'; +} from '../../common/types'; +import { cacheGet } from '../cache'; +import * as Registry from '../registry'; -interface PackageRequest extends Request { - params: { - pkgkey: string; - }; -} - -interface InstallFeatureRequest extends PackageRequest { - params: { - pkgkey: string; - feature: string; - }; -} - -export async function handleGetList(req: Request) { - const registryItems = await Registry.fetchList(); - const searchObjects: SavedObjectsBulkGetObject[] = registryItems.map(({ name, version }) => ({ - type: SAVED_OBJECT_TYPE, - id: `${name}-${version}`, - })); - const client = getClient(req); - const results = await client.bulkGet(searchObjects); - const savedObjects: InstallationSavedObject[] = results.saved_objects.filter(o => !o.error); // ignore errors for now - const integrationList = createIntegrationList(registryItems, savedObjects); - - return integrationList; -} - -export async function handleGetInfo(req: PackageRequest) { - const { pkgkey } = req.params; - const item = await Registry.fetchInfo(pkgkey); - const savedObject = await getInstallationObject(getClient(req), pkgkey); - const installation = createInstallationObject(item, savedObject); - - return installation; -} - -export async function handleRequestInstall(req: InstallFeatureRequest) { - const { pkgkey, feature } = req.params; - - if (feature === 'dashboard') { - const toBeSavedObjects = await getObjects(pkgkey, feature); - const client = getClient(req); - const createResults = await client.bulkCreate(toBeSavedObjects, { overwrite: true }); - const installed = createResults.saved_objects.map(({ id, type }) => ({ id, type })); - const mgrResults = await client.create( - SAVED_OBJECT_TYPE, - { installed }, - { id: pkgkey, overwrite: true } - ); - - return mgrResults; - } - - return { - pkgkey, - feature, - created: [], - }; -} - -export async function handleRequestDelete(req: InstallFeatureRequest) { - const { pkgkey, feature } = req.params; - const client = getClient(req); - - const installation = await getInstallationObject(client, pkgkey); - const installedObjects = (installation && installation.attributes.installed) || []; - - // Delete the manager saved object with references to the asset objects - // could also update with [] or some other state - await client.delete(SAVED_OBJECT_TYPE, pkgkey); - - // ASK: should the manager uninstall the assets it installed - // or just the references in SAVED_OBJECT_TYPE? - if (feature === 'dashboard') { - // Delete the installed assets - const deletePromises = installedObjects.map(async ({ id, type }) => client.delete(type, id)); - await Promise.all(deletePromises); - } - - return { - pkgkey, - feature, - deleted: installedObjects, - }; -} - -export async function getObjects(pkgkey: string, type: string): Promise { - const paths = await Registry.getArchiveInfo(`${pkgkey}.tar.gz`); - const toBeSavedObjects = paths.reduce((map, path) => { - collectReferences(map, { path, desiredType: 'dashboard' }); - return map; - }, new Map()); - - return Array.from(toBeSavedObjects.values(), ensureJsonValues); -} +export * from './handlers'; function getAsset(key: string) { const value = cacheGet(key); @@ -174,7 +77,7 @@ function ensureJsonValues(obj: SavedObject) { return obj; } -function createIntegrationList( +export function createIntegrationList( registryItems: RegistryList, integrationObjects: InstallationSavedObject[] ) { @@ -188,15 +91,15 @@ function createIntegrationList( return integrationList.sort(sortByName); } -function createInstallationObject( +export function createInstallationObject( item: RegistryPackage, savedObject?: InstallationSavedObject ): IntegrationInfo; -function createInstallationObject( +export function createInstallationObject( item: RegistryListItem, savedObject?: InstallationSavedObject ): IntegrationListItem; -function createInstallationObject( +export function createInstallationObject( obj: RegistryPackage | RegistryListItem, savedObject?: InstallationSavedObject ) { @@ -222,9 +125,19 @@ function sortByName(a: { name: string }, b: { name: string }) { } } -async function getInstallationObject( +export async function getInstallationObject( client: SavedObjectsClientContract, pkgkey: string ): Promise { return client.get(SAVED_OBJECT_TYPE, pkgkey).catch(e => undefined); } + +export async function getObjects(pkgkey: string, type: string): Promise { + const paths = await Registry.getArchiveInfo(`${pkgkey}.tar.gz`); + const toBeSavedObjects = paths.reduce((map, path) => { + collectReferences(map, { path, desiredType: 'dashboard' }); + return map; + }, new Map()); + + return Array.from(toBeSavedObjects.values(), ensureJsonValues); +} From e89b5b02281ae4ae343465ade04aa0d06c8ad509 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Tue, 9 Jul 2019 11:52:43 -0400 Subject: [PATCH 02/11] Do what I wanted to do initially but didn't know how. --- .../integrations_manager/server/integrations/handlers.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts index a125414e2245c..2e442f3fc8db6 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts @@ -23,8 +23,7 @@ interface PackageRequest extends Request { } interface InstallFeatureRequest extends PackageRequest { - params: { - pkgkey: string; + params: PackageRequest['params'] & { feature: string; }; } From 5c37b3ac419152a67bd83f35471ad53f63dc1d57 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Tue, 9 Jul 2019 12:06:20 -0400 Subject: [PATCH 03/11] Pull in renames from 40548-correct-asset-names --- .../integrations_manager/common/routes.ts | 4 ++-- .../server/integrations/handlers.ts | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/common/routes.ts b/x-pack/legacy/plugins/integrations_manager/common/routes.ts index 6b594c26e0869..82f41066784bf 100644 --- a/x-pack/legacy/plugins/integrations_manager/common/routes.ts +++ b/x-pack/legacy/plugins/integrations_manager/common/routes.ts @@ -8,8 +8,8 @@ import { PLUGIN_ID } from './constants'; export const API_ROOT = `/api/${PLUGIN_ID}`; export const API_LIST_PATTERN = `${API_ROOT}/list`; export const API_INFO_PATTERN = `${API_ROOT}/package/{pkgkey}`; -export const API_INSTALL_PATTERN = `${API_ROOT}/install/{pkgkey}/{feature?}`; -export const API_DELETE_PATTERN = `${API_ROOT}/delete/{pkgkey}/{feature?}`; +export const API_INSTALL_PATTERN = `${API_ROOT}/install/{pkgkey}/{asset?}`; +export const API_DELETE_PATTERN = `${API_ROOT}/delete/{pkgkey}/{asset?}`; export function getListPath() { return API_LIST_PATTERN; diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts index 2e442f3fc8db6..66b439a88fad8 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts @@ -22,9 +22,9 @@ interface PackageRequest extends Request { }; } -interface InstallFeatureRequest extends PackageRequest { +interface InstallAssetRequest extends PackageRequest { params: PackageRequest['params'] & { - feature: string; + asset: string; }; } @@ -51,11 +51,11 @@ export async function handleGetInfo(req: PackageRequest) { return installation; } -export async function handleRequestInstall(req: InstallFeatureRequest) { - const { pkgkey, feature } = req.params; +export async function handleRequestInstall(req: InstallAssetRequest) { + const { pkgkey, asset } = req.params; - if (feature === 'dashboard') { - const toBeSavedObjects = await getObjects(pkgkey, feature); + if (asset === 'dashboard') { + const toBeSavedObjects = await getObjects(pkgkey, asset); const client = getClient(req); const createResults = await client.bulkCreate(toBeSavedObjects, { overwrite: true }); const installed = createResults.saved_objects.map(({ id, type }) => ({ id, type })); @@ -70,13 +70,13 @@ export async function handleRequestInstall(req: InstallFeatureRequest) { return { pkgkey, - feature, + asset, created: [], }; } -export async function handleRequestDelete(req: InstallFeatureRequest) { - const { pkgkey, feature } = req.params; +export async function handleRequestDelete(req: InstallAssetRequest) { + const { pkgkey, asset } = req.params; const client = getClient(req); const installation = await getInstallationObject(client, pkgkey); @@ -88,7 +88,7 @@ export async function handleRequestDelete(req: InstallFeatureRequest) { // ASK: should the manager uninstall the assets it installed // or just the references in SAVED_OBJECT_TYPE? - if (feature === 'dashboard') { + if (asset === 'dashboard') { // Delete the installed assets const deletePromises = installedObjects.map(async ({ id, type }) => client.delete(type, id)); await Promise.all(deletePromises); @@ -96,7 +96,7 @@ export async function handleRequestDelete(req: InstallFeatureRequest) { return { pkgkey, - feature, + asset, deleted: installedObjects, }; } From f81e67017c8ad595bc1ae5d9e1f56e578892cb87 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Tue, 9 Jul 2019 15:54:02 -0400 Subject: [PATCH 04/11] index -> {handlers,data,registry}.ts. Handlers parse reqs; call data fns Behavior should be unchanged. --- .../integrations_manager/common/types.ts | 10 +- .../server/integrations/data.ts | 107 ++++++++++++++ .../server/integrations/handlers.ts | 56 ++----- .../server/integrations/index.ts | 137 +----------------- .../integrations_manager/server/registry.ts | 65 +++++++++ 5 files changed, 189 insertions(+), 186 deletions(-) create mode 100644 x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts diff --git a/x-pack/legacy/plugins/integrations_manager/common/types.ts b/x-pack/legacy/plugins/integrations_manager/common/types.ts index a8dde6e80ed45..8c499dac48c42 100644 --- a/x-pack/legacy/plugins/integrations_manager/common/types.ts +++ b/x-pack/legacy/plugins/integrations_manager/common/types.ts @@ -49,15 +49,17 @@ export interface RegistryPackage { // the public HTTP response types export type IntegrationList = IntegrationListItem[]; -export type IntegrationListItem = Installed | NotInstalled; +export type IntegrationListItem = Installable; -export type IntegrationInfo = Installed | NotInstalled; +export type IntegrationInfo = Installable; -type Installed = T & { +export type Installable = Installed | NotInstalled; + +export type Installed = T & { status: 'installed'; savedObject: InstallationSavedObject; }; -type NotInstalled = T & { +export type NotInstalled = T & { status: 'not_installed'; }; diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts new file mode 100644 index 0000000000000..94761bd70440c --- /dev/null +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + SavedObjectsBulkGetObject, + SavedObjectsClientContract, +} from 'src/core/server/saved_objects'; +import { InstallationSavedObject, Installable } from '../../common/types'; +import { SAVED_OBJECT_TYPE } from '../../common/constants'; +import * as Registry from '../registry'; + +export async function getIntegrations(client: SavedObjectsClientContract) { + const registryItems = await Registry.fetchList(); + const searchObjects: SavedObjectsBulkGetObject[] = registryItems.map(({ name, version }) => ({ + type: SAVED_OBJECT_TYPE, + id: `${name}-${version}`, + })); + + const results = await client.bulkGet(searchObjects); + const savedObjects: InstallationSavedObject[] = results.saved_objects.filter(o => !o.error); // ignore errors for now + const integrationList = registryItems + .map(item => + createInstallableFrom( + item, + savedObjects.find(({ id }) => id === `${item.name}-${item.version}`) + ) + ) + .sort(sortByName); + + return integrationList; +} + +export async function getIntegrationInfo(client: SavedObjectsClientContract, pkgkey: string) { + const [item, savedObject] = await Promise.all([ + Registry.fetchInfo(pkgkey), + getInstallationObject(client, pkgkey), + ]); + const installation = createInstallableFrom(item, savedObject); + + return installation; +} + +export async function getInstallationObject( + client: SavedObjectsClientContract, + pkgkey: string +): Promise { + return client.get(SAVED_OBJECT_TYPE, pkgkey).catch(e => undefined); +} + +export async function installAssets( + client: SavedObjectsClientContract, + pkgkey: string, + asset: string +) { + const toBeSavedObjects = await Registry.getObjects(pkgkey, asset); + const createResults = await client.bulkCreate(toBeSavedObjects, { overwrite: true }); + const installed = createResults.saved_objects.map(({ id, type }) => ({ id, type })); + const results = await client.create( + SAVED_OBJECT_TYPE, + { installed }, + { id: pkgkey, overwrite: true } + ); + + return results; +} + +export async function removeInstallation(client: SavedObjectsClientContract, pkgkey: string) { + const installation = await getInstallationObject(client, pkgkey); + const installedObjects = (installation && installation.attributes.installed) || []; + + // Delete the manager saved object with references to the asset objects + // could also update with [] or some other state + await client.delete(SAVED_OBJECT_TYPE, pkgkey); + + // Delete the installed assets + const deletePromises = installedObjects.map(async ({ id, type }) => client.delete(type, id)); + await Promise.all(deletePromises); + + // successful delete's in SO client return {}. return something more useful + return installedObjects; +} + +function sortByName(a: { name: string }, b: { name: string }) { + if (a.name > b.name) { + return 1; + } else if (a.name < b.name) { + return -1; + } else { + return 0; + } +} + +function createInstallableFrom(from: T, savedObject?: InstallationSavedObject): Installable { + return savedObject + ? { + ...from, + status: 'installed', + savedObject, + } + : { + ...from, + status: 'not_installed', + }; +} diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts index 66b439a88fad8..62d68c9879024 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts @@ -4,17 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedObjectsBulkGetObject } from 'src/core/server/saved_objects'; import { Request, InstallationSavedObject } from '../../common/types'; -import { SAVED_OBJECT_TYPE } from '../../common/constants'; -import { - createInstallationObject, - createIntegrationList, - getInstallationObject, - getObjects, -} from './index'; -import * as Registry from '../registry'; import { getClient } from '../saved_objects'; +import { getIntegrations, getIntegrationInfo, installAssets, removeInstallation } from './data'; interface PackageRequest extends Request { params: { @@ -29,74 +21,46 @@ interface InstallAssetRequest extends PackageRequest { } export async function handleGetList(req: Request) { - const registryItems = await Registry.fetchList(); - const searchObjects: SavedObjectsBulkGetObject[] = registryItems.map(({ name, version }) => ({ - type: SAVED_OBJECT_TYPE, - id: `${name}-${version}`, - })); const client = getClient(req); - const results = await client.bulkGet(searchObjects); - const savedObjects: InstallationSavedObject[] = results.saved_objects.filter(o => !o.error); // ignore errors for now - const integrationList = createIntegrationList(registryItems, savedObjects); + const integrationList = await getIntegrations(client); return integrationList; } export async function handleGetInfo(req: PackageRequest) { const { pkgkey } = req.params; - const item = await Registry.fetchInfo(pkgkey); - const savedObject = await getInstallationObject(getClient(req), pkgkey); - const installation = createInstallationObject(item, savedObject); + const client = getClient(req); + const installation = await getIntegrationInfo(client, pkgkey); return installation; } export async function handleRequestInstall(req: InstallAssetRequest) { const { pkgkey, asset } = req.params; + const created: InstallationSavedObject[] = []; if (asset === 'dashboard') { - const toBeSavedObjects = await getObjects(pkgkey, asset); const client = getClient(req); - const createResults = await client.bulkCreate(toBeSavedObjects, { overwrite: true }); - const installed = createResults.saved_objects.map(({ id, type }) => ({ id, type })); - const mgrResults = await client.create( - SAVED_OBJECT_TYPE, - { installed }, - { id: pkgkey, overwrite: true } - ); + const object = await installAssets(client, pkgkey, asset); - return mgrResults; + created.push(object); } return { pkgkey, asset, - created: [], + created, }; } export async function handleRequestDelete(req: InstallAssetRequest) { const { pkgkey, asset } = req.params; const client = getClient(req); - - const installation = await getInstallationObject(client, pkgkey); - const installedObjects = (installation && installation.attributes.installed) || []; - - // Delete the manager saved object with references to the asset objects - // could also update with [] or some other state - await client.delete(SAVED_OBJECT_TYPE, pkgkey); - - // ASK: should the manager uninstall the assets it installed - // or just the references in SAVED_OBJECT_TYPE? - if (asset === 'dashboard') { - // Delete the installed assets - const deletePromises = installedObjects.map(async ({ id, type }) => client.delete(type, id)); - await Promise.all(deletePromises); - } + const deleted = await removeInstallation(client, pkgkey); return { pkgkey, asset, - deleted: installedObjects, + deleted, }; } diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/index.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/index.ts index 392d817d21ce2..9e640ddb30dc6 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/index.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/index.ts @@ -4,140 +4,5 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - SavedObject, - SavedObjectReference, - SavedObjectsClientContract, -} from 'src/core/server/saved_objects'; -import { SAVED_OBJECT_TYPE } from '../../common/constants'; -import { - InstallationSavedObject, - IntegrationInfo, - IntegrationListItem, - RegistryList, - RegistryListItem, - RegistryPackage, -} from '../../common/types'; -import { cacheGet } from '../cache'; -import * as Registry from '../registry'; - +export * from './data'; export * from './handlers'; - -function getAsset(key: string) { - const value = cacheGet(key); - if (value !== undefined) { - const json = value.toString('utf8'); - return JSON.parse(json); - } -} - -interface CollectReferencesOptions { - path: string; - desiredType: string; // TODO: from enum or similar of acceptable asset types -} -function collectReferences( - toBeSavedObjects: Map = new Map(), - { path, desiredType = 'dashboard' }: CollectReferencesOptions -) { - const [pkgkey, service, type, file] = path.split('/'); - if (type !== desiredType) return; - if (toBeSavedObjects.has(path)) return; - if (!/\.json$/.test(path)) return; - - const asset = getAsset(path); - if (!asset.type) asset.type = type; - if (!asset.id) asset.id = file.replace('.json', ''); - toBeSavedObjects.set(path, asset); - - const references: SavedObjectReference[] = asset.references; - return references.reduce((map, reference) => { - collectReferences(toBeSavedObjects, { - path: `${pkgkey}/${service}/${reference.type}/${reference.id}.json`, - desiredType: reference.type, - }); - return map; - }, toBeSavedObjects); -} - -// the assets from the registry are malformed -// https://github.com/elastic/integrations-registry/issues/42 -function ensureJsonValues(obj: SavedObject) { - const { attributes } = obj; - if ( - attributes.kibanaSavedObjectMeta && - typeof attributes.kibanaSavedObjectMeta.searchSourceJSON !== 'string' - ) { - attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify( - attributes.kibanaSavedObjectMeta.searchSourceJSON - ); - } - ['optionsJSON', 'panelsJSON', 'uiStateJSON', 'visState'] - .filter(key => typeof attributes[key] !== 'string') - .forEach(key => (attributes[key] = JSON.stringify(attributes[key]))); - return obj; -} - -export function createIntegrationList( - registryItems: RegistryList, - integrationObjects: InstallationSavedObject[] -) { - const integrationList = registryItems.map(item => - createInstallationObject( - item, - integrationObjects.find(({ id }) => id === `${item.name}-${item.version}`) - ) - ); - - return integrationList.sort(sortByName); -} - -export function createInstallationObject( - item: RegistryPackage, - savedObject?: InstallationSavedObject -): IntegrationInfo; -export function createInstallationObject( - item: RegistryListItem, - savedObject?: InstallationSavedObject -): IntegrationListItem; -export function createInstallationObject( - obj: RegistryPackage | RegistryListItem, - savedObject?: InstallationSavedObject -) { - return savedObject - ? { - ...obj, - status: 'installed', - savedObject, - } - : { - ...obj, - status: 'not_installed', - }; -} - -function sortByName(a: { name: string }, b: { name: string }) { - if (a.name > b.name) { - return 1; - } else if (a.name < b.name) { - return -1; - } else { - return 0; - } -} - -export async function getInstallationObject( - client: SavedObjectsClientContract, - pkgkey: string -): Promise { - return client.get(SAVED_OBJECT_TYPE, pkgkey).catch(e => undefined); -} - -export async function getObjects(pkgkey: string, type: string): Promise { - const paths = await Registry.getArchiveInfo(`${pkgkey}.tar.gz`); - const toBeSavedObjects = paths.reduce((map, path) => { - collectReferences(map, { path, desiredType: 'dashboard' }); - return map; - }, new Map()); - - return Array.from(toBeSavedObjects.values(), ensureJsonValues); -} diff --git a/x-pack/legacy/plugins/integrations_manager/server/registry.ts b/x-pack/legacy/plugins/integrations_manager/server/registry.ts index c6adb81c15090..b75be2ee3ddb4 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/registry.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/registry.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { SavedObject, SavedObjectReference } from 'src/core/server/saved_objects'; import { RegistryList, RegistryPackage } from '../common/types'; import { cacheGet, cacheSet, cacheHas } from './cache'; import { ArchiveEntry, untarBuffer, unzipBuffer } from './extract'; @@ -65,3 +66,67 @@ async function getOrFetchArchiveBuffer(key: string): Promise { async function fetchArchiveBuffer(key: string): Promise { return getResponseStream(`${REGISTRY}/package/${key}`).then(streamToBuffer); } + +export async function getObjects(pkgkey: string, desiredType?: string): Promise { + const paths = await getArchiveInfo(`${pkgkey}.tar.gz`); + const toBeSavedObjects = paths.reduce((map, path) => { + collectReferences(map, { path, desiredType }); + return map; + }, new Map()); + + return Array.from(toBeSavedObjects.values(), ensureJsonValues); +} + +interface CollectReferencesOptions { + path: string; + desiredType?: string; // TODO: from enum or similar of acceptable asset types +} +function collectReferences( + toBeSavedObjects: Map = new Map(), + { path, desiredType }: CollectReferencesOptions +) { + const [pkgkey, service, type, file] = path.split('/'); + if (type !== desiredType) return; + if (toBeSavedObjects.has(path)) return; + if (!/\.json$/.test(path)) return; + + const asset = getAsset(path); + if (!asset.type) asset.type = type; + if (!asset.id) asset.id = file.replace('.json', ''); + toBeSavedObjects.set(path, asset); + + const references: SavedObjectReference[] = asset.references; + return references.reduce((map, reference) => { + collectReferences(toBeSavedObjects, { + path: `${pkgkey}/${service}/${reference.type}/${reference.id}.json`, + desiredType: reference.type, + }); + return map; + }, toBeSavedObjects); +} + +// the assets from the registry are malformed +// https://github.com/elastic/integrations-registry/issues/42 +function ensureJsonValues(obj: SavedObject) { + const { attributes } = obj; + if ( + attributes.kibanaSavedObjectMeta && + typeof attributes.kibanaSavedObjectMeta.searchSourceJSON !== 'string' + ) { + attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify( + attributes.kibanaSavedObjectMeta.searchSourceJSON + ); + } + ['optionsJSON', 'panelsJSON', 'uiStateJSON', 'visState'] + .filter(key => typeof attributes[key] !== 'string') + .forEach(key => (attributes[key] = JSON.stringify(attributes[key]))); + return obj; +} + +function getAsset(key: string) { + const value = cacheGet(key); + if (value !== undefined) { + const json = value.toString('utf8'); + return JSON.parse(json); + } +} From f7379492ec56099c6322842ecce7ffa5d3780b37 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Tue, 9 Jul 2019 17:39:12 -0400 Subject: [PATCH 05/11] Fix eslint/prettier issues. Not sure what happened --- .../integrations_manager/public/screens/detail.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/public/screens/detail.tsx b/x-pack/legacy/plugins/integrations_manager/public/screens/detail.tsx index 783ddfeacc50d..cdc6198186da6 100644 --- a/x-pack/legacy/plugins/integrations_manager/public/screens/detail.tsx +++ b/x-pack/legacy/plugins/integrations_manager/public/screens/detail.tsx @@ -10,12 +10,9 @@ import { IntegrationInfo } from '../../common/types'; export function Detail(props: { package: string }) { const [info, setInfo] = useState(null); - useEffect( - () => { - getIntegrationInfoByKey(props.package).then(setInfo); - }, - [props.package] - ); + useEffect(() => { + getIntegrationInfoByKey(props.package).then(setInfo); + }, [props.package]); // don't have designs for loading/empty states if (!info) return null; From 0f2ba7388ee3b71ec25d3b024e63f3b8981703ea Mon Sep 17 00:00:00 2001 From: John Schulz Date: Wed, 10 Jul 2019 14:51:39 -0400 Subject: [PATCH 06/11] getObjects: accept a filter function & comments for getting references. This is consistent with other registry functions. Returned to nested for loops internally. --- .../server/integrations/data.ts | 8 +- .../server/integrations/handlers.ts | 11 +- .../integrations_manager/server/registry.ts | 100 +++++++++++------- 3 files changed, 76 insertions(+), 43 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts index 94761bd70440c..f95098d90cb8e 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts @@ -5,6 +5,7 @@ */ import { + SavedObject, SavedObjectsBulkGetObject, SavedObjectsClientContract, } from 'src/core/server/saved_objects'; @@ -53,11 +54,12 @@ export async function getInstallationObject( export async function installAssets( client: SavedObjectsClientContract, pkgkey: string, - asset: string + filter = (entry: Registry.ArchiveEntry): boolean => true ) { - const toBeSavedObjects = await Registry.getObjects(pkgkey, asset); + const toBeSavedObjects = await Registry.getObjects(pkgkey, filter); const createResults = await client.bulkCreate(toBeSavedObjects, { overwrite: true }); - const installed = createResults.saved_objects.map(({ id, type }) => ({ id, type })); + const createdObjects: SavedObject[] = createResults.saved_objects; + const installed = createdObjects.map(({ id, type }) => ({ id, type })); const results = await client.create( SAVED_OBJECT_TYPE, { installed }, diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts index 62d68c9879024..b3f4a4a48dab8 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts @@ -5,6 +5,7 @@ */ import { Request, InstallationSavedObject } from '../../common/types'; +import { ArchiveEntry, pathParts } from '../registry'; import { getClient } from '../saved_objects'; import { getIntegrations, getIntegrationInfo, installAssets, removeInstallation } from './data'; @@ -20,6 +21,9 @@ interface InstallAssetRequest extends PackageRequest { }; } +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface DeleteAssetRequest extends InstallAssetRequest {} + export async function handleGetList(req: Request) { const client = getClient(req); const integrationList = await getIntegrations(client); @@ -41,7 +45,10 @@ export async function handleRequestInstall(req: InstallAssetRequest) { if (asset === 'dashboard') { const client = getClient(req); - const object = await installAssets(client, pkgkey, asset); + const object = await installAssets(client, pkgkey, (entry: ArchiveEntry) => { + const { type } = pathParts(entry.path); + return type === asset; + }); created.push(object); } @@ -53,7 +60,7 @@ export async function handleRequestInstall(req: InstallAssetRequest) { }; } -export async function handleRequestDelete(req: InstallAssetRequest) { +export async function handleRequestDelete(req: DeleteAssetRequest) { const { pkgkey, asset } = req.params; const client = getClient(req); const deleted = await removeInstallation(client, pkgkey); diff --git a/x-pack/legacy/plugins/integrations_manager/server/registry.ts b/x-pack/legacy/plugins/integrations_manager/server/registry.ts index b75be2ee3ddb4..f155075fbedf3 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/registry.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/registry.ts @@ -4,13 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedObject, SavedObjectReference } from 'src/core/server/saved_objects'; +import { SavedObject } from 'src/core/server/saved_objects'; import { RegistryList, RegistryPackage } from '../common/types'; import { cacheGet, cacheSet, cacheHas } from './cache'; import { ArchiveEntry, untarBuffer, unzipBuffer } from './extract'; import { fetchUrl, getResponseStream } from './requests'; import { streamToBuffer } from './streams'; +export { ArchiveEntry } from './extract'; + const REGISTRY = process.env.REGISTRY || 'http://integrations-registry.app.elstc.co'; export async function fetchList(): Promise { @@ -28,9 +30,13 @@ export async function getArchiveInfo( const paths: string[] = []; const onEntry = (entry: ArchiveEntry) => { const { path, buffer } = entry; - paths.push(path); + const { file } = pathParts(path); + if (!file) return; if (cacheHas(path)) return; - if (buffer) cacheSet(path, buffer); + if (buffer) { + cacheSet(path, buffer); + paths.push(path); + } }; await extract(key, filter, onEntry); @@ -67,42 +73,48 @@ async function fetchArchiveBuffer(key: string): Promise { return getResponseStream(`${REGISTRY}/package/${key}`).then(streamToBuffer); } -export async function getObjects(pkgkey: string, desiredType?: string): Promise { - const paths = await getArchiveInfo(`${pkgkey}.tar.gz`); - const toBeSavedObjects = paths.reduce((map, path) => { - collectReferences(map, { path, desiredType }); - return map; - }, new Map()); +export async function getObjects( + pkgkey: string, + filter = (entry: ArchiveEntry): boolean => true +): Promise { + // Create a Map b/c some values, especially index-patterns, are referenced multiple times + const objects: Map = new Map(); + + // Get paths which match the given filter + const paths = await getArchiveInfo(`${pkgkey}.tar.gz`, filter); + + // Add all objects which matched filter to the Map + paths.map(getObject).forEach(obj => objects.set(obj.id, obj)); + + // Each of those objects might have `references` property like [{id, type, name}] + for (const object of objects.values()) { + // For each of those objects + for (const reference of object.references) { + // Get the objects they reference. Call same function with a new filter + const referencedObjects = await getObjects(pkgkey, (entry: ArchiveEntry) => { + // Skip anything we've already stored + if (objects.has(reference.id)) return false; + + // Is the archive entry the reference we want? + const { type, file } = pathParts(entry.path); + const isType = type === reference.type; + const isJson = file === `${reference.id}.json`; + return isType && isJson; + }); + + // Add referenced objects to the Map + referencedObjects.forEach(ro => objects.set(ro.id, ro)); + } + } - return Array.from(toBeSavedObjects.values(), ensureJsonValues); + // return the array of unique objects + return Array.from(objects.values()); } -interface CollectReferencesOptions { - path: string; - desiredType?: string; // TODO: from enum or similar of acceptable asset types -} -function collectReferences( - toBeSavedObjects: Map = new Map(), - { path, desiredType }: CollectReferencesOptions -) { +export function pathParts(path: string) { const [pkgkey, service, type, file] = path.split('/'); - if (type !== desiredType) return; - if (toBeSavedObjects.has(path)) return; - if (!/\.json$/.test(path)) return; - const asset = getAsset(path); - if (!asset.type) asset.type = type; - if (!asset.id) asset.id = file.replace('.json', ''); - toBeSavedObjects.set(path, asset); - - const references: SavedObjectReference[] = asset.references; - return references.reduce((map, reference) => { - collectReferences(toBeSavedObjects, { - path: `${pkgkey}/${service}/${reference.type}/${reference.id}.json`, - desiredType: reference.type, - }); - return map; - }, toBeSavedObjects); + return { pkgkey, service, type, file }; } // the assets from the registry are malformed @@ -125,8 +137,20 @@ function ensureJsonValues(obj: SavedObject) { function getAsset(key: string) { const value = cacheGet(key); - if (value !== undefined) { - const json = value.toString('utf8'); - return JSON.parse(json); - } + if (value === undefined) throw new Error(`Cannot find asset ${key}`); + + const json = value.toString('utf8'); + const asset = JSON.parse(json); + + return asset; +} + +function getObject(key: string) { + const asset = getAsset(key); + const { type, file } = pathParts(key); + + if (!asset.type) asset.type = type; + if (!asset.id) asset.id = file.replace('.json', ''); + + return ensureJsonValues(asset); } From 04247a42c37a4a5a8023187c14b634405a5f2881 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Wed, 10 Jul 2019 16:18:28 -0400 Subject: [PATCH 07/11] Reorder so all `export`ed functions are at the top of the file. --- .../integrations_manager/server/registry.ts | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/server/registry.ts b/x-pack/legacy/plugins/integrations_manager/server/registry.ts index f155075fbedf3..7d485e613db42 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/registry.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/registry.ts @@ -44,35 +44,6 @@ export async function getArchiveInfo( return paths; } -async function extract( - key: string, - filter = (entry: ArchiveEntry): boolean => true, - onEntry: (entry: ArchiveEntry) => void -) { - const libExtract = key.endsWith('.zip') ? unzipBuffer : untarBuffer; - const archiveBuffer = await getOrFetchArchiveBuffer(key); - - return libExtract(archiveBuffer, filter, onEntry); -} - -async function getOrFetchArchiveBuffer(key: string): Promise { - let buffer = cacheGet(key); - if (!buffer) { - buffer = await fetchArchiveBuffer(key); - cacheSet(key, buffer); - } - - if (buffer) { - return buffer; - } else { - throw new Error(`no archive buffer for ${key}`); - } -} - -async function fetchArchiveBuffer(key: string): Promise { - return getResponseStream(`${REGISTRY}/package/${key}`).then(streamToBuffer); -} - export async function getObjects( pkgkey: string, filter = (entry: ArchiveEntry): boolean => true @@ -117,6 +88,35 @@ export function pathParts(path: string) { return { pkgkey, service, type, file }; } +async function extract( + key: string, + filter = (entry: ArchiveEntry): boolean => true, + onEntry: (entry: ArchiveEntry) => void +) { + const libExtract = key.endsWith('.zip') ? unzipBuffer : untarBuffer; + const archiveBuffer = await getOrFetchArchiveBuffer(key); + + return libExtract(archiveBuffer, filter, onEntry); +} + +async function getOrFetchArchiveBuffer(key: string): Promise { + let buffer = cacheGet(key); + if (!buffer) { + buffer = await fetchArchiveBuffer(key); + cacheSet(key, buffer); + } + + if (buffer) { + return buffer; + } else { + throw new Error(`no archive buffer for ${key}`); + } +} + +async function fetchArchiveBuffer(key: string): Promise { + return getResponseStream(`${REGISTRY}/package/${key}`).then(streamToBuffer); +} + // the assets from the registry are malformed // https://github.com/elastic/integrations-registry/issues/42 function ensureJsonValues(obj: SavedObject) { From 5437febe0e26f5e7641e8895211346e27c81be9c Mon Sep 17 00:00:00 2001 From: John Schulz Date: Wed, 10 Jul 2019 16:20:56 -0400 Subject: [PATCH 08/11] Collapse `getAsset` into `getObject`. Add some comments. Don't need a generic accessor (e.g. for docs, images, etc) yet. Will factor out when it's needed. --- .../integrations_manager/server/registry.ts | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/server/registry.ts b/x-pack/legacy/plugins/integrations_manager/server/registry.ts index 7d485e613db42..621132b2349ab 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/registry.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/registry.ts @@ -135,22 +135,18 @@ function ensureJsonValues(obj: SavedObject) { return obj; } -function getAsset(key: string) { - const value = cacheGet(key); - if (value === undefined) throw new Error(`Cannot find asset ${key}`); - - const json = value.toString('utf8'); - const asset = JSON.parse(json); +function getObject(key: string) { + const buffer = cacheGet(key); + if (buffer === undefined) throw new Error(`Cannot find asset ${key}`); - return asset; -} + // cache values are buffers. convert to string / JSON + const json = buffer.toString('utf8'); + // convert that to an object & address issues with the formatting of some parts + const asset = ensureJsonValues(JSON.parse(json)); -function getObject(key: string) { - const asset = getAsset(key); const { type, file } = pathParts(key); - if (!asset.type) asset.type = type; if (!asset.id) asset.id = file.replace('.json', ''); - return ensureJsonValues(asset); + return asset; } From 9b978e94dd168dd1598e4d775f90c6cb1c834af2 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Wed, 10 Jul 2019 16:23:01 -0400 Subject: [PATCH 09/11] Add a name for intermediate value. Avoid extra iterations. I think this is clearer. It also makes sure we don't loop over any keys other than the "root" ones we just matched (vs all that are in the map/accumulator). --- .../legacy/plugins/integrations_manager/server/registry.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/server/registry.ts b/x-pack/legacy/plugins/integrations_manager/server/registry.ts index 621132b2349ab..2497b53415b1a 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/registry.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/registry.ts @@ -54,11 +54,12 @@ export async function getObjects( // Get paths which match the given filter const paths = await getArchiveInfo(`${pkgkey}.tar.gz`, filter); - // Add all objects which matched filter to the Map - paths.map(getObject).forEach(obj => objects.set(obj.id, obj)); + // Get all objects which matched filter. Add them to the Map + const rootObjects = paths.map(getObject); + rootObjects.forEach(obj => objects.set(obj.id, obj)); // Each of those objects might have `references` property like [{id, type, name}] - for (const object of objects.values()) { + for (const object of rootObjects) { // For each of those objects for (const reference of object.references) { // Get the objects they reference. Call same function with a new filter From 13cef20c5c90936c5c494d9e917e37d40b25dfc4 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Wed, 10 Jul 2019 16:30:42 -0400 Subject: [PATCH 10/11] Request interfaces no extend already extend values. Add a param type. --- .../server/integrations/handlers.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts index b3f4a4a48dab8..9b6ab9d77e448 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts @@ -15,14 +15,17 @@ interface PackageRequest extends Request { }; } -interface InstallAssetRequest extends PackageRequest { - params: PackageRequest['params'] & { - asset: string; - }; +interface InstallAssetRequest extends Request { + params: AssetRequestParams; +} + +interface DeleteAssetRequest extends Request { + params: AssetRequestParams; } -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface DeleteAssetRequest extends InstallAssetRequest {} +type AssetRequestParams = PackageRequest['params'] & { + asset: string; +}; export async function handleGetList(req: Request) { const client = getClient(req); From 98dfac89375b258a4219fe515745c5b8ae477602 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Wed, 10 Jul 2019 17:12:41 -0400 Subject: [PATCH 11/11] Change two names related to Saved Objects. Call SO client with types. --- .../integrations_manager/common/types.ts | 6 +++--- .../server/integrations/data.ts | 21 +++++++++---------- .../server/integrations/handlers.ts | 4 ++-- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/x-pack/legacy/plugins/integrations_manager/common/types.ts b/x-pack/legacy/plugins/integrations_manager/common/types.ts index 8c499dac48c42..388e08148a282 100644 --- a/x-pack/legacy/plugins/integrations_manager/common/types.ts +++ b/x-pack/legacy/plugins/integrations_manager/common/types.ts @@ -12,11 +12,11 @@ import { } from 'src/core/server/saved_objects'; type AssetReference = Pick; -export interface Installation extends SavedObjectAttributes { +export interface InstallationAttributes extends SavedObjectAttributes { installed: AssetReference[]; } -export type InstallationSavedObject = SavedObject; +export type Installation = SavedObject; // the contract with the registry export type RegistryList = RegistryListItem[]; @@ -57,7 +57,7 @@ export type Installable = Installed | NotInstalled; export type Installed = T & { status: 'installed'; - savedObject: InstallationSavedObject; + savedObject: Installation; }; export type NotInstalled = T & { diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts index f95098d90cb8e..35cce5703d9ca 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/data.ts @@ -9,7 +9,7 @@ import { SavedObjectsBulkGetObject, SavedObjectsClientContract, } from 'src/core/server/saved_objects'; -import { InstallationSavedObject, Installable } from '../../common/types'; +import { Installation, InstallationAttributes, Installable } from '../../common/types'; import { SAVED_OBJECT_TYPE } from '../../common/constants'; import * as Registry from '../registry'; @@ -20,8 +20,8 @@ export async function getIntegrations(client: SavedObjectsClientContract) { id: `${name}-${version}`, })); - const results = await client.bulkGet(searchObjects); - const savedObjects: InstallationSavedObject[] = results.saved_objects.filter(o => !o.error); // ignore errors for now + const results = await client.bulkGet(searchObjects); + const savedObjects = results.saved_objects.filter(o => !o.error); // ignore errors for now const integrationList = registryItems .map(item => createInstallableFrom( @@ -44,11 +44,8 @@ export async function getIntegrationInfo(client: SavedObjectsClientContract, pkg return installation; } -export async function getInstallationObject( - client: SavedObjectsClientContract, - pkgkey: string -): Promise { - return client.get(SAVED_OBJECT_TYPE, pkgkey).catch(e => undefined); +export async function getInstallationObject(client: SavedObjectsClientContract, pkgkey: string) { + return client.get(SAVED_OBJECT_TYPE, pkgkey).catch(e => undefined); } export async function installAssets( @@ -57,10 +54,12 @@ export async function installAssets( filter = (entry: Registry.ArchiveEntry): boolean => true ) { const toBeSavedObjects = await Registry.getObjects(pkgkey, filter); - const createResults = await client.bulkCreate(toBeSavedObjects, { overwrite: true }); + const createResults = await client.bulkCreate(toBeSavedObjects, { + overwrite: true, + }); const createdObjects: SavedObject[] = createResults.saved_objects; const installed = createdObjects.map(({ id, type }) => ({ id, type })); - const results = await client.create( + const results = await client.create( SAVED_OBJECT_TYPE, { installed }, { id: pkgkey, overwrite: true } @@ -95,7 +94,7 @@ function sortByName(a: { name: string }, b: { name: string }) { } } -function createInstallableFrom(from: T, savedObject?: InstallationSavedObject): Installable { +function createInstallableFrom(from: T, savedObject?: Installation): Installable { return savedObject ? { ...from, diff --git a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts index 9b6ab9d77e448..3f5f4e9452057 100644 --- a/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts +++ b/x-pack/legacy/plugins/integrations_manager/server/integrations/handlers.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request, InstallationSavedObject } from '../../common/types'; +import { Request } from '../../common/types'; import { ArchiveEntry, pathParts } from '../registry'; import { getClient } from '../saved_objects'; import { getIntegrations, getIntegrationInfo, installAssets, removeInstallation } from './data'; @@ -44,7 +44,7 @@ export async function handleGetInfo(req: PackageRequest) { export async function handleRequestInstall(req: InstallAssetRequest) { const { pkgkey, asset } = req.params; - const created: InstallationSavedObject[] = []; + const created = []; if (asset === 'dashboard') { const client = getClient(req);