-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Fleet] Add custom integrations API #112481
Merged
thomasneirynck
merged 36 commits into
elastic:master
from
thomasneirynck:fleet/add_custom_categories
Sep 27, 2021
Merged
Changes from 12 commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
b87be67
initial boilerplate
thomasneirynck 5ca5307
setup dependency in fleet
thomasneirynck c6175ad
add custom cards to UX (boilerplate)
thomasneirynck 46a67e5
remove cruft
thomasneirynck 3844e8a
isolate epr from cards
thomasneirynck a40cee6
make cards generic
thomasneirynck 950a9a2
remove epr-typing from cards
thomasneirynck 4bc93e0
remove epr tpying from card-lists
thomasneirynck 5c4258e
more typing
thomasneirynck 4d0a763
Merge branch 'master' of github.com:elastic/kibana into fleet/add_cus…
thomasneirynck df06051
more type fixes
thomasneirynck fc0ed69
Fix icon issue
thomasneirynck 9f217dd
Merge branch 'master' of github.com:elastic/kibana into fleet/add_cus…
thomasneirynck 2d459d2
resolve a few CI checks
thomasneirynck 3e9e58d
test
thomasneirynck 0a21901
fix linting with new settings
thomasneirynck d0ba72a
remove faulty import
thomasneirynck f41f8fc
feedback
thomasneirynck 85753fd
feedback
thomasneirynck 04fe290
rename for clarity
thomasneirynck e155137
fix typo
thomasneirynck 25c43dc
update plugin manifest
thomasneirynck 69d05b8
home tests
thomasneirynck 6df5f7b
fleet mocks
thomasneirynck c05ff99
home setup/start test
thomasneirynck f9b6164
dont merge in place
thomasneirynck 77a571f
ignore ts error in test
thomasneirynck e1e4c63
move badge-labels back inside card-component
thomasneirynck cfc5c4d
remove unused
thomasneirynck e96bc0b
Merge branch 'master' of github.com:elastic/kibana into fleet/add_cus…
thomasneirynck 29e7028
feedback
thomasneirynck e9e769e
remove cruft
thomasneirynck d73f38d
add jest boilerplate
thomasneirynck 7fddfb7
Fill in test coverage
thomasneirynck 6d63a02
Merge branch 'master' of github.com:elastic/kibana into fleet/add_cus…
thomasneirynck 0450645
Merge branch 'master' of github.com:elastic/kibana into fleet/add_cus…
thomasneirynck File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# customIntegrations | ||
|
||
Register add-data cards | ||
|
||
--- | ||
|
||
## Development | ||
|
||
See the [kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md) for instructions setting up your development environment. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
export const PLUGIN_ID = 'customIntegrations'; | ||
export const PLUGIN_NAME = 'customIntegrations'; | ||
|
||
export interface CategoryCount { | ||
count: number; | ||
id: Category; | ||
} | ||
|
||
// todo internationalize | ||
thomasneirynck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
export const CATEGORY_DISPLAY = { | ||
aws: 'AWS', | ||
azure: 'Azure', | ||
cloud: 'Cloud', | ||
config_management: 'Config management', | ||
containers: 'Containers', | ||
crm: 'CRM', | ||
custom: 'Custom', | ||
datastore: 'Datastore', | ||
elastic_stack: 'Elastic Stack', | ||
google_cloud: 'Google cloud', | ||
kubernetes: 'Kubernetes', | ||
languages: 'Languages', | ||
message_queue: 'Message queue', | ||
monitoring: 'Monitoring', | ||
network: 'Network', | ||
notification: 'Notification', | ||
os_system: 'OS & System', | ||
productivity: 'Productivity', | ||
security: 'Security', | ||
sample_data: 'Sample data', | ||
support: 'Support', | ||
ticketing: 'Ticketing', | ||
version_control: 'Version control', | ||
web: 'Web', | ||
upload_file: 'Upload a file', | ||
|
||
updates_available: 'Updates available', | ||
}; | ||
|
||
export type Category = keyof typeof CATEGORY_DISPLAY; | ||
|
||
export interface CustomIntegration { | ||
id: string; | ||
title: string; | ||
name: string; | ||
description: string; | ||
type: 'ui_link'; | ||
thomasneirynck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
uiInternalPath: string; | ||
isBeta: boolean; | ||
icons: Array<{ src: string; type: string }>; | ||
categories: Category[]; | ||
shipper: string; | ||
eprPackageOverlap?: string; | ||
thomasneirynck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
export const ROUTES_ADDABLECUSTOMINTEGRATIONS = `/api/${PLUGIN_ID}/addableCustomIntegrations`; | ||
export const ROUTES_REPLACEABLECUSTOMINMTEGRATIONS = `/api/${PLUGIN_ID}/replaceableCustomIntegrations`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"id": "customIntegrations", | ||
"version": "1.0.0", | ||
"kibanaVersion": "kibana", | ||
"owner": { | ||
"name": "platform", | ||
"githubTeam": "" | ||
thomasneirynck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
"description": "test", | ||
"ui": true, | ||
"server": true, | ||
"extraPublicDirs": [ | ||
"common" | ||
], | ||
"optionalPlugins": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { CustomIntegrationPlugin } from './plugin'; | ||
|
||
// This exports static code and TypeScript types, | ||
// as well as, Kibana Platform `plugin()` initializer. | ||
export function plugin() { | ||
return new CustomIntegrationPlugin(); | ||
} | ||
export { CustomIntegrationsSetup, CustomIntegrationsStart } from './types'; | ||
thomasneirynck marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; | ||
import { CustomIntegrationsSetup, CustomIntegrationsStart } from './types'; | ||
import { | ||
CustomIntegration, | ||
ROUTES_ADDABLECUSTOMINTEGRATIONS, | ||
ROUTES_REPLACEABLECUSTOMINMTEGRATIONS, | ||
} from '../common'; | ||
|
||
export class CustomIntegrationPlugin | ||
implements Plugin<CustomIntegrationsSetup, CustomIntegrationsStart> { | ||
public setup(core: CoreSetup): CustomIntegrationsSetup { | ||
// Return methods that should be available to other plugins | ||
return { | ||
async getAddableCustomIntegrations(): Promise<CustomIntegration[]> { | ||
return core.http.get(ROUTES_ADDABLECUSTOMINTEGRATIONS); | ||
}, | ||
async getReplaceableCustomIntegrations(): Promise<CustomIntegration[]> { | ||
return core.http.get(ROUTES_REPLACEABLECUSTOMINMTEGRATIONS); | ||
}, | ||
} as CustomIntegrationsSetup; | ||
} | ||
|
||
public start(core: CoreStart): CustomIntegrationsStart { | ||
return {}; | ||
} | ||
|
||
public stop() {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { CustomIntegration } from '../common'; | ||
|
||
export interface CustomIntegrationsSetup { | ||
getReplaceableCustomIntegrations: () => Promise<CustomIntegration[]>; | ||
getAddableCustomIntegrations: () => Promise<CustomIntegration[]>; | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-empty-interface | ||
export interface CustomIntegrationsStart {} | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-empty-interface | ||
export interface AppPluginStartDependencies {} |
74 changes: 74 additions & 0 deletions
74
src/plugins/custom_integrations/server/custom_integration_registry.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { Logger } from 'kibana/server'; | ||
import { CustomIntegration, CategoryCount, Category } from '../common'; | ||
|
||
function isAddable(integration: CustomIntegration) { | ||
return integration.categories.length; | ||
} | ||
|
||
export class CustomIntegrationRegistry { | ||
private readonly _integrations: CustomIntegration[]; | ||
private readonly _logger: Logger; | ||
|
||
constructor(logger: Logger) { | ||
this._integrations = []; | ||
this._logger = logger; | ||
} | ||
|
||
registerCustomIntegration(customIntegration: CustomIntegration) { | ||
if ( | ||
this._integrations.some((integration: CustomIntegration) => { | ||
return integration.name === customIntegration.name; | ||
}) | ||
) { | ||
this._logger.error(`Integration with id=${customIntegration.name} already exists.`); | ||
thomasneirynck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return; | ||
} | ||
|
||
this._integrations.push(customIntegration); | ||
} | ||
|
||
getAddableCustomIntegrations(): CustomIntegration[] { | ||
return this._integrations.filter(isAddable); | ||
} | ||
|
||
getReplaceableCustomIntegrations(): CustomIntegration[] { | ||
return this._integrations.filter( | ||
(integration) => typeof integration.eprPackageOverlap !== 'undefined' | ||
); | ||
} | ||
|
||
getAddableCategories(): CategoryCount[] { | ||
const categories: Map<Category, number> = new Map<Category, number>(); | ||
for (let i = 0; i < this._integrations.length; i++) { | ||
if (!isAddable(this._integrations[i])) { | ||
continue; | ||
} | ||
for (let j = 0; j < this._integrations[i].categories.length; j++) { | ||
const category = this._integrations[i].categories[j]; | ||
if (categories.has(category)) { | ||
// @ts-ignore | ||
categories.set(category, categories.get(category) + 1); | ||
} else { | ||
categories.set(category, 1); | ||
} | ||
} | ||
} | ||
|
||
const list: CategoryCount[] = []; | ||
categories.forEach((value, key) => { | ||
list.push({ | ||
count: value, | ||
id: key, | ||
}); | ||
}); | ||
return list; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { PluginInitializerContext } from '../../../core/server'; | ||
import { CustomIntegrationsPlugin } from './plugin'; | ||
|
||
// This exports static code and TypeScript types, | ||
// as well as, Kibana Platform `plugin()` initializer. | ||
|
||
export function plugin(initializerContext: PluginInitializerContext) { | ||
return new CustomIntegrationsPlugin(initializerContext); | ||
} | ||
|
||
export { CustomIntegrationsPluginSetup, CustomIntegrationsPluginStart } from './types'; | ||
|
||
export type { Category, CategoryCount, CustomIntegration } from '../common'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from 'kibana/server'; | ||
|
||
import { CustomIntegrationsPluginSetup, CustomIntegrationsPluginStart } from './types'; | ||
import { CustomIntegration, CategoryCount } from '../common'; | ||
import { CustomIntegrationRegistry } from './custom_integration_registry'; | ||
import { defineRoutes } from './routes/define_routes'; | ||
|
||
export class CustomIntegrationsPlugin | ||
implements Plugin<CustomIntegrationsPluginSetup, CustomIntegrationsPluginStart> { | ||
private readonly logger: Logger; | ||
private readonly customIngegrationRegistry: CustomIntegrationRegistry; | ||
|
||
constructor(initializerContext: PluginInitializerContext) { | ||
this.logger = initializerContext.logger.get(); | ||
this.customIngegrationRegistry = new CustomIntegrationRegistry(this.logger); | ||
} | ||
|
||
public setup(core: CoreSetup) { | ||
this.logger.debug('customIntegrations: Setup'); | ||
|
||
const router = core.http.createRouter(); | ||
defineRoutes(router, this.customIngegrationRegistry); | ||
|
||
return { | ||
registerCustomIntegration: (integration: CustomIntegration) => { | ||
this.customIngegrationRegistry.registerCustomIntegration(integration); | ||
}, | ||
getAddableCustomIntegrations: (): CustomIntegration[] => { | ||
return this.customIngegrationRegistry.getAddableCustomIntegrations(); | ||
}, | ||
|
||
getAddableCategories: (): CategoryCount[] => { | ||
return this.customIngegrationRegistry.getAddableCategories(); | ||
}, | ||
getReplaceableCustomIntegrations: (): CustomIntegration[] => { | ||
return this.customIngegrationRegistry.getReplaceableCustomIntegrations(); | ||
}, | ||
} as CustomIntegrationsPluginSetup; | ||
} | ||
|
||
public start(core: CoreStart) { | ||
this.logger.debug('customIntegrations: Started'); | ||
return {}; | ||
} | ||
|
||
public stop() {} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/plugins/custom_integrations/server/routes/define_routes.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { IRouter } from 'src/core/server'; | ||
import { CustomIntegrationRegistry } from '../custom_integration_registry'; | ||
import { | ||
ROUTES_ADDABLECUSTOMINTEGRATIONS, | ||
ROUTES_REPLACEABLECUSTOMINMTEGRATIONS, | ||
} from '../../common'; | ||
|
||
export function defineRoutes( | ||
router: IRouter, | ||
customIntegrationsRegistry: CustomIntegrationRegistry | ||
) { | ||
router.get( | ||
{ | ||
path: ROUTES_ADDABLECUSTOMINTEGRATIONS, | ||
validate: false, | ||
}, | ||
async (context, request, response) => { | ||
const integrations = customIntegrationsRegistry.getAddableCustomIntegrations(); | ||
return response.ok({ | ||
body: integrations, | ||
}); | ||
} | ||
); | ||
|
||
router.get( | ||
{ | ||
path: ROUTES_REPLACEABLECUSTOMINMTEGRATIONS, | ||
validate: false, | ||
}, | ||
async (context, request, response) => { | ||
const integrations = customIntegrationsRegistry.getReplaceableCustomIntegrations(); | ||
return response.ok({ | ||
body: integrations, | ||
}); | ||
} | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { CustomIntegration, CategoryCount } from '../common'; | ||
|
||
export interface CustomIntegrationsPluginSetup { | ||
registerCustomIntegration(customIntegration: CustomIntegration): void; | ||
getAddableCustomIntegrations(): CustomIntegration[]; | ||
getAddableCategories(): CategoryCount[]; | ||
getReplaceableCustomIntegrations(): CustomIntegration[]; | ||
thomasneirynck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-empty-interface | ||
export interface CustomIntegrationsPluginStart {} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docs will need fleshing out and conversion to
.mdx
if we want to include them in the new dev docsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx. my preference is to hold off on dev-docs in this PR. These will evolve fairly quickly. Would prefer to introduce only in separate PR when contract stabilizes.