Skip to content

Commit

Permalink
[Integrations UI] Add support for custom asset definitions in Integra…
Browse files Browse the repository at this point in the history
…tion assets tab (elastic#103554)

* Add UI extension logic for assets + set up custom log views

* Add endpoint security UI extension

* Add synthetics ui extension

* Address PR feedback

- Remove default filter for log stream url
- Fix missing basePath prepend on asset urls
- Expand accordion by default on assetless integrations

* Fix type errors

* Add initial APM extension setup

* Fix missing ExtensionWrapper for enrollment extension

* Fix custom logs asset extension

* Fix type errors

* Add new hook for enrollment flyout ui extensions

* Address PR review + refactor UI extension usage for flyout

* Update limits.yml via script

* Fix type errors

* Add tests for custom assets UI extensions

* Update tests for flyout

* Remove unused import

* Fix type errors in ui extension tests

* Skip view data tests and link to issue

* Use RedirectAppLinks + fix synthetics link

* Use constants for app ID's where possible

* Revert limits.yml

* Fix lazy imports for custom asset components

* Update endpoint custom assets link + description

* Add translation for custom assets UI

* Address PR review in APM

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
kpollich and kibanamachine authored Jul 1, 2021
1 parent 1c82ad2 commit 059ed08
Show file tree
Hide file tree
Showing 39 changed files with 669 additions and 161 deletions.
23 changes: 12 additions & 11 deletions x-pack/plugins/apm/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,34 @@
"version": "8.0.0",
"kibanaVersion": "kibana",
"requiredPlugins": [
"features",
"apmOss",
"data",
"licensing",
"triggersActionsUi",
"embeddable",
"features",
"fleet",
"infra",
"licensing",
"observability",
"ruleRegistry"
"ruleRegistry",
"triggersActionsUi"
],
"optionalPlugins": [
"spaces",
"cloud",
"usageCollection",
"taskManager",
"actions",
"alerting",
"security",
"ml",
"cloud",
"home",
"maps",
"fleet"
"ml",
"security",
"spaces",
"taskManager",
"usageCollection"
],
"server": true,
"ui": true,
"configPath": ["xpack", "apm"],
"requiredBundles": [
"fleet",
"home",
"kibanaReact",
"kibanaUtils",
Expand Down
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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import { i18n } from '@kbn/i18n';

import {
CustomAssetsAccordionProps,
CustomAssetsAccordion,
} from '../../../../fleet/public';
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
import { ApmPluginStartDeps } from '../../plugin';

export function ApmCustomAssetsExtension() {
const { http } = useKibana<ApmPluginStartDeps>().services;
const basePath = http?.basePath.get();

const views: CustomAssetsAccordionProps['views'] = [
{
name: i18n.translate('xpack.apm.fleetIntegration.assets.name', {
defaultMessage: 'Services',
}),
url: `${basePath}/app/apm`,
description: i18n.translate(
'xpack.apm.fleetIntegration.assets.description',
{ defaultMessage: 'View application traces and service maps in APM' }
),
},
];

return <CustomAssetsAccordion views={views} initialIsOpen />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import { EuiButton, EuiText, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { AgentEnrollmentFlyoutFinalStepExtension } from '../../../../fleet/public';
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
import { ApmPluginStartDeps } from '../../plugin';

function StepComponent() {
const { http } = useKibana<ApmPluginStartDeps>().services;
const installApmAgentLink = http?.basePath.prepend('/app/home#/tutorial/apm');

return (
<>
<EuiText>
<p>
{i18n.translate(
'xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentDescription',
{
defaultMessage:
'After the agent starts, you can install APM agents on your hosts to collect data from your applications and services.',
}
)}
</p>
</EuiText>
<EuiSpacer size="m" />

<EuiButton fill href={installApmAgentLink}>
{i18n.translate(
'xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentButtonText',
{ defaultMessage: 'Install APM Agent' }
)}
</EuiButton>
</>
);
}

export function getApmEnrollmentFlyoutData(): Pick<
AgentEnrollmentFlyoutFinalStepExtension,
'title' | 'Component'
> {
return {
title: i18n.translate(
'xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentTitle',
{
defaultMessage: 'Install APM Agent',
}
),
Component: StepComponent,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export * from './apm_enrollment_flyout_extension';
export * from './lazy_apm_custom_assets_extension';
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { lazy } from 'react';

export const LazyApmCustomAssetsExtension = lazy(async () => {
const { ApmCustomAssetsExtension } = await import(
'./apm_custom_assets_extension'
);

return {
default: ApmCustomAssetsExtension,
};
});
25 changes: 24 additions & 1 deletion x-pack/plugins/apm/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {
DataPublicPluginStart,
} from '../../../../src/plugins/data/public';
import type { EmbeddableStart } from '../../../../src/plugins/embeddable/public';
import type { FleetStart } from '../../fleet/public';
import type { HomePublicPluginSetup } from '../../../../src/plugins/home/public';
import type {
PluginSetupContract as AlertingPluginPublicSetup,
Expand All @@ -43,6 +44,10 @@ import type {
} from '../../triggers_actions_ui/public';
import { registerApmAlerts } from './components/alerting/register_apm_alerts';
import { featureCatalogueEntry } from './featureCatalogueEntry';
import {
getApmEnrollmentFlyoutData,
LazyApmCustomAssetsExtension,
} from './components/fleet_integration';

export type ApmPluginSetup = ReturnType<ApmPlugin['setup']>;

Expand All @@ -69,6 +74,7 @@ export interface ApmPluginStartDeps {
ml?: MlPluginStart;
triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
observability: ObservabilityPublicStart;
fleet: FleetStart;
}

export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
Expand Down Expand Up @@ -303,5 +309,22 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {

return {};
}
public start(core: CoreStart, plugins: ApmPluginStartDeps) {}
public start(core: CoreStart, plugins: ApmPluginStartDeps) {
const { fleet } = plugins;

const agentEnrollmentExtensionData = getApmEnrollmentFlyoutData();

fleet.registerExtension({
package: 'apm',
view: 'agent-enrollment-flyout',
title: agentEnrollmentExtensionData.title,
Component: agentEnrollmentExtensionData.Component,
});

fleet.registerExtension({
package: 'apm',
view: 'package-detail-assets',
Component: LazyApmCustomAssetsExtension,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
[params, updatePackageInfo, agentPolicy, updateAgentPolicy, queryParamsPolicyId]
);

const ExtensionView = useUIExtension(packagePolicy.package?.name ?? '', 'package-policy-create');
const extensionView = useUIExtension(packagePolicy.package?.name ?? '', 'package-policy-create');

const stepConfigurePackagePolicy = useMemo(
() =>
Expand All @@ -444,7 +444,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
/>

{/* Only show the out-of-box configuration step if a UI extension is NOT registered */}
{!ExtensionView && (
{!extensionView && (
<StepConfigurePackagePolicy
packageInfo={packageInfo}
showOnlyIntegration={integrationInfo?.name}
Expand All @@ -456,9 +456,12 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
)}

{/* If an Agent Policy and a package has been selected, then show UI extension (if any) */}
{ExtensionView && packagePolicy.policy_id && packagePolicy.package?.name && (
{extensionView && packagePolicy.policy_id && packagePolicy.package?.name && (
<ExtensionWrapper>
<ExtensionView newPolicy={packagePolicy} onChange={handleExtensionViewOnChange} />
<extensionView.Component
newPolicy={packagePolicy}
onChange={handleExtensionViewOnChange}
/>
</ExtensionWrapper>
)}
</>
Expand All @@ -474,7 +477,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => {
validationResults,
formState,
integrationInfo?.name,
ExtensionView,
extensionView,
handleExtensionViewOnChange,
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ export const EditPackagePolicyForm = memo<{
packageInfo,
};

const ExtensionView = useUIExtension(packagePolicy.package?.name ?? '', 'package-policy-edit');
const extensionView = useUIExtension(packagePolicy.package?.name ?? '', 'package-policy-edit');

const configurePackage = useMemo(
() =>
Expand All @@ -354,7 +354,7 @@ export const EditPackagePolicyForm = memo<{
/>

{/* Only show the out-of-box configuration step if a UI extension is NOT registered */}
{!ExtensionView && (
{!extensionView && (
<StepConfigurePackagePolicy
packageInfo={packageInfo}
packagePolicy={packagePolicy}
Expand All @@ -364,12 +364,12 @@ export const EditPackagePolicyForm = memo<{
/>
)}

{ExtensionView &&
{extensionView &&
packagePolicy.policy_id &&
packagePolicy.package?.name &&
originalPackagePolicy && (
<ExtensionWrapper>
<ExtensionView
<extensionView.Component
policy={originalPackagePolicy}
newPolicy={packagePolicy}
onChange={handleExtensionViewOnChange}
Expand All @@ -386,7 +386,7 @@ export const EditPackagePolicyForm = memo<{
validationResults,
formState,
originalPackagePolicy,
ExtensionView,
extensionView,
handleExtensionViewOnChange,
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const DisplayedAssets: ServiceNameToAssetTypes = {
elasticsearch: Object.values(ElasticsearchAssetType),
};

export type DisplayedAssetType = ElasticsearchAssetType | KibanaAssetType;
export type DisplayedAssetType = ElasticsearchAssetType | KibanaAssetType | 'view';

export const AssetTitleMap: Record<DisplayedAssetType, string> = {
dashboard: 'Dashboard',
Expand All @@ -36,6 +36,7 @@ export const AssetTitleMap: Record<DisplayedAssetType, string> = {
lens: 'Lens',
security_rule: 'Security Rule',
ml_module: 'ML Module',
view: 'Views',
};

export const ServiceTitleMap: Record<ServiceName, string> = {
Expand Down
Loading

0 comments on commit 059ed08

Please sign in to comment.