* [Fleet] Show callout when EPR unavailable (#117598) * Update src/core/public/doc_links/doc_links_service.ts Co-authored-by: Thomas Neirynck <thomas@elastic.co>
This commit is contained in:
parent
76fbc4b545
commit
7ca4a3a666
|
@ -243,6 +243,7 @@ readonly links: {
|
||||||
fleetServerAddFleetServer: string;
|
fleetServerAddFleetServer: string;
|
||||||
settings: string;
|
settings: string;
|
||||||
settingsFleetServerHostSettings: string;
|
settingsFleetServerHostSettings: string;
|
||||||
|
settingsFleetServerProxySettings: string;
|
||||||
troubleshooting: string;
|
troubleshooting: string;
|
||||||
elasticAgent: string;
|
elasticAgent: string;
|
||||||
datastreams: string;
|
datastreams: string;
|
||||||
|
@ -252,6 +253,7 @@ readonly links: {
|
||||||
upgradeElasticAgent712lower: string;
|
upgradeElasticAgent712lower: string;
|
||||||
learnMoreBlog: string;
|
learnMoreBlog: string;
|
||||||
apiKeysLearnMore: string;
|
apiKeysLearnMore: string;
|
||||||
|
onPremRegistry: string;
|
||||||
}>;
|
}>;
|
||||||
readonly ecs: {
|
readonly ecs: {
|
||||||
readonly guide: string;
|
readonly guide: string;
|
||||||
|
|
|
@ -488,6 +488,7 @@ export class DocLinksService {
|
||||||
fleetServerAddFleetServer: `${FLEET_DOCS}fleet-server.html#add-fleet-server`,
|
fleetServerAddFleetServer: `${FLEET_DOCS}fleet-server.html#add-fleet-server`,
|
||||||
settings: `${FLEET_DOCS}fleet-settings.html#fleet-server-hosts-setting`,
|
settings: `${FLEET_DOCS}fleet-settings.html#fleet-server-hosts-setting`,
|
||||||
settingsFleetServerHostSettings: `${FLEET_DOCS}fleet-settings.html#fleet-server-hosts-setting`,
|
settingsFleetServerHostSettings: `${FLEET_DOCS}fleet-settings.html#fleet-server-hosts-setting`,
|
||||||
|
settingsFleetServerProxySettings: `${KIBANA_DOCS}fleet-settings-kb.html#fleet-data-visualizer-settings`,
|
||||||
troubleshooting: `${FLEET_DOCS}fleet-troubleshooting.html`,
|
troubleshooting: `${FLEET_DOCS}fleet-troubleshooting.html`,
|
||||||
elasticAgent: `${FLEET_DOCS}elastic-agent-installation.html`,
|
elasticAgent: `${FLEET_DOCS}elastic-agent-installation.html`,
|
||||||
beatsAgentComparison: `${FLEET_DOCS}beats-agent-comparison.html`,
|
beatsAgentComparison: `${FLEET_DOCS}beats-agent-comparison.html`,
|
||||||
|
@ -499,6 +500,7 @@ export class DocLinksService {
|
||||||
upgradeElasticAgent712lower: `${FLEET_DOCS}upgrade-elastic-agent.html#upgrade-7.12-lower`,
|
upgradeElasticAgent712lower: `${FLEET_DOCS}upgrade-elastic-agent.html#upgrade-7.12-lower`,
|
||||||
learnMoreBlog: `${ELASTIC_WEBSITE_URL}blog/elastic-agent-and-fleet-make-it-easier-to-integrate-your-systems-with-elastic`,
|
learnMoreBlog: `${ELASTIC_WEBSITE_URL}blog/elastic-agent-and-fleet-make-it-easier-to-integrate-your-systems-with-elastic`,
|
||||||
apiKeysLearnMore: `${KIBANA_DOCS}api-keys.html`,
|
apiKeysLearnMore: `${KIBANA_DOCS}api-keys.html`,
|
||||||
|
onPremRegistry: `${ELASTIC_WEBSITE_URL}guide/en/integrations-developer/current/air-gapped.html`,
|
||||||
},
|
},
|
||||||
ecs: {
|
ecs: {
|
||||||
guide: `${ELASTIC_WEBSITE_URL}guide/en/ecs/current/index.html`,
|
guide: `${ELASTIC_WEBSITE_URL}guide/en/ecs/current/index.html`,
|
||||||
|
@ -764,6 +766,7 @@ export interface DocLinksStart {
|
||||||
fleetServerAddFleetServer: string;
|
fleetServerAddFleetServer: string;
|
||||||
settings: string;
|
settings: string;
|
||||||
settingsFleetServerHostSettings: string;
|
settingsFleetServerHostSettings: string;
|
||||||
|
settingsFleetServerProxySettings: string;
|
||||||
troubleshooting: string;
|
troubleshooting: string;
|
||||||
elasticAgent: string;
|
elasticAgent: string;
|
||||||
datastreams: string;
|
datastreams: string;
|
||||||
|
@ -773,6 +776,7 @@ export interface DocLinksStart {
|
||||||
upgradeElasticAgent712lower: string;
|
upgradeElasticAgent712lower: string;
|
||||||
learnMoreBlog: string;
|
learnMoreBlog: string;
|
||||||
apiKeysLearnMore: string;
|
apiKeysLearnMore: string;
|
||||||
|
onPremRegistry: string;
|
||||||
}>;
|
}>;
|
||||||
readonly ecs: {
|
readonly ecs: {
|
||||||
readonly guide: string;
|
readonly guide: string;
|
||||||
|
|
|
@ -713,6 +713,7 @@ export interface DocLinksStart {
|
||||||
fleetServerAddFleetServer: string;
|
fleetServerAddFleetServer: string;
|
||||||
settings: string;
|
settings: string;
|
||||||
settingsFleetServerHostSettings: string;
|
settingsFleetServerHostSettings: string;
|
||||||
|
settingsFleetServerProxySettings: string;
|
||||||
troubleshooting: string;
|
troubleshooting: string;
|
||||||
elasticAgent: string;
|
elasticAgent: string;
|
||||||
datastreams: string;
|
datastreams: string;
|
||||||
|
@ -722,6 +723,7 @@ export interface DocLinksStart {
|
||||||
upgradeElasticAgent712lower: string;
|
upgradeElasticAgent712lower: string;
|
||||||
learnMoreBlog: string;
|
learnMoreBlog: string;
|
||||||
apiKeysLearnMore: string;
|
apiKeysLearnMore: string;
|
||||||
|
onPremRegistry: string;
|
||||||
}>;
|
}>;
|
||||||
readonly ecs: {
|
readonly ecs: {
|
||||||
readonly guide: string;
|
readonly guide: string;
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { FunctionComponent } from 'react';
|
||||||
import React, { memo, useMemo, useState } from 'react';
|
import React, { memo, useMemo, useState } from 'react';
|
||||||
import { useLocation, useHistory, useParams } from 'react-router-dom';
|
import { useLocation, useHistory, useParams } from 'react-router-dom';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import { FormattedMessage } from '@kbn/i18n/react';
|
||||||
import {
|
import {
|
||||||
EuiHorizontalRule,
|
EuiHorizontalRule,
|
||||||
EuiFlexItem,
|
EuiFlexItem,
|
||||||
|
@ -16,6 +18,8 @@ import {
|
||||||
EuiSpacer,
|
EuiSpacer,
|
||||||
EuiCard,
|
EuiCard,
|
||||||
EuiIcon,
|
EuiIcon,
|
||||||
|
EuiCallOut,
|
||||||
|
EuiLink,
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
|
|
||||||
import { useStartServices } from '../../../../hooks';
|
import { useStartServices } from '../../../../hooks';
|
||||||
|
@ -52,6 +56,76 @@ import type { CategoryFacet } from './category_facets';
|
||||||
import type { CategoryParams } from '.';
|
import type { CategoryParams } from '.';
|
||||||
import { getParams, categoryExists, mapToCard } from '.';
|
import { getParams, categoryExists, mapToCard } from '.';
|
||||||
|
|
||||||
|
const NoEprCallout: FunctionComponent<{ statusCode?: number }> = ({
|
||||||
|
statusCode,
|
||||||
|
}: {
|
||||||
|
statusCode?: number;
|
||||||
|
}) => {
|
||||||
|
let titleMessage;
|
||||||
|
let descriptionMessage;
|
||||||
|
if (statusCode === 502) {
|
||||||
|
titleMessage = i18n.translate('xpack.fleet.epmList.eprUnavailableBadGatewayCalloutTitle', {
|
||||||
|
defaultMessage:
|
||||||
|
'Kibana cannot reach the Elastic Package Registry, which provides Elastic Agent integrations\n',
|
||||||
|
});
|
||||||
|
descriptionMessage = (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.fleet.epmList.eprUnavailableCallouBdGatewaytTitleMessage"
|
||||||
|
defaultMessage="To view these integrations, configure a {registryproxy} or host {onpremregistry}."
|
||||||
|
values={{
|
||||||
|
registryproxy: <ProxyLink />,
|
||||||
|
onpremregistry: <OnPremLink />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
titleMessage = i18n.translate('xpack.fleet.epmList.eprUnavailable400500CalloutTitle', {
|
||||||
|
defaultMessage:
|
||||||
|
'Kibana cannot connect to the Elastic Package Registry, which provides Elastic Agent integrations\n',
|
||||||
|
});
|
||||||
|
descriptionMessage = (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.fleet.epmList.eprUnavailableCallout400500TitleMessage"
|
||||||
|
defaultMessage="Ensure the {registryproxy} or {onpremregistry} is configured correctly, or try again later."
|
||||||
|
values={{
|
||||||
|
registryproxy: <ProxyLink />,
|
||||||
|
onpremregistry: <OnPremLink />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiCallOut title={titleMessage} iconType="iInCircle" color={'warning'}>
|
||||||
|
<p>{descriptionMessage}</p>
|
||||||
|
</EuiCallOut>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function ProxyLink() {
|
||||||
|
const { docLinks } = useStartServices();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiLink href={docLinks.links.fleet.settingsFleetServerProxySettings} target="_blank">
|
||||||
|
{i18n.translate('xpack.fleet.epmList.proxyLinkSnippedText', {
|
||||||
|
defaultMessage: 'proxy server',
|
||||||
|
})}
|
||||||
|
</EuiLink>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function OnPremLink() {
|
||||||
|
const { docLinks } = useStartServices();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiLink href={docLinks.links.fleet.onPremRegistry} target="_blank">
|
||||||
|
{i18n.translate('xpack.fleet.epmList.onPremLinkSnippetText', {
|
||||||
|
defaultMessage: 'your own registry',
|
||||||
|
})}
|
||||||
|
</EuiLink>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function getAllCategoriesFromIntegrations(pkg: PackageListItem) {
|
function getAllCategoriesFromIntegrations(pkg: PackageListItem) {
|
||||||
if (!doesPackageHaveIntegrations(pkg)) {
|
if (!doesPackageHaveIntegrations(pkg)) {
|
||||||
return pkg.categories;
|
return pkg.categories;
|
||||||
|
@ -133,10 +207,13 @@ export const AvailablePackages: React.FC = memo(() => {
|
||||||
history.replace(pagePathGetters.integrations_all({ searchTerm: search })[1]);
|
history.replace(pagePathGetters.integrations_all({ searchTerm: search })[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: eprPackages, isLoading: isLoadingAllPackages } = useGetPackages({
|
const {
|
||||||
|
data: eprPackages,
|
||||||
|
isLoading: isLoadingAllPackages,
|
||||||
|
error: eprPackageLoadingError,
|
||||||
|
} = useGetPackages({
|
||||||
category: '',
|
category: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const eprIntegrationList = useMemo(
|
const eprIntegrationList = useMemo(
|
||||||
() => packageListToIntegrationsList(eprPackages?.response || []),
|
() => packageListToIntegrationsList(eprPackages?.response || []),
|
||||||
[eprPackages]
|
[eprPackages]
|
||||||
|
@ -166,18 +243,23 @@ export const AvailablePackages: React.FC = memo(() => {
|
||||||
return a.title.localeCompare(b.title);
|
return a.title.localeCompare(b.title);
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: eprCategories, isLoading: isLoadingCategories } = useGetCategories({
|
const {
|
||||||
|
data: eprCategories,
|
||||||
|
isLoading: isLoadingCategories,
|
||||||
|
error: eprCategoryLoadingError,
|
||||||
|
} = useGetCategories({
|
||||||
include_policy_templates: true,
|
include_policy_templates: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const categories = useMemo(() => {
|
const categories = useMemo(() => {
|
||||||
const eprAndCustomCategories: CategoryFacet[] =
|
const eprAndCustomCategories: CategoryFacet[] = isLoadingCategories
|
||||||
isLoadingCategories || !eprCategories
|
? []
|
||||||
? []
|
: mergeCategoriesAndCount(
|
||||||
: mergeCategoriesAndCount(
|
eprCategories
|
||||||
eprCategories.response as Array<{ id: string; title: string; count: number }>,
|
? (eprCategories.response as Array<{ id: string; title: string; count: number }>)
|
||||||
cards
|
: [],
|
||||||
);
|
cards
|
||||||
|
);
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
...ALL_CATEGORY,
|
...ALL_CATEGORY,
|
||||||
|
@ -281,6 +363,12 @@ export const AvailablePackages: React.FC = memo(() => {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let noEprCallout;
|
||||||
|
if (eprPackageLoadingError || eprCategoryLoadingError) {
|
||||||
|
const error = eprPackageLoadingError || eprCategoryLoadingError;
|
||||||
|
noEprCallout = <NoEprCallout statusCode={error?.statusCode} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PackageListGrid
|
<PackageListGrid
|
||||||
featuredList={featuredList}
|
featuredList={featuredList}
|
||||||
|
@ -291,6 +379,7 @@ export const AvailablePackages: React.FC = memo(() => {
|
||||||
setSelectedCategory={setSelectedCategory}
|
setSelectedCategory={setSelectedCategory}
|
||||||
onSearchChange={setSearchTerm}
|
onSearchChange={setSearchTerm}
|
||||||
showMissingIntegrationMessage
|
showMissingIntegrationMessage
|
||||||
|
callout={noEprCallout}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,9 @@ import {
|
||||||
IngestManagerError,
|
IngestManagerError,
|
||||||
PackageNotFoundError,
|
PackageNotFoundError,
|
||||||
PackageUnsupportedMediaTypeError,
|
PackageUnsupportedMediaTypeError,
|
||||||
|
RegistryConnectionError,
|
||||||
RegistryError,
|
RegistryError,
|
||||||
|
RegistryResponseError,
|
||||||
} from './index';
|
} from './index';
|
||||||
|
|
||||||
type IngestErrorHandler = (
|
type IngestErrorHandler = (
|
||||||
|
@ -40,7 +42,12 @@ interface IngestErrorHandlerParams {
|
||||||
// this type is based on BadRequest values observed while debugging https://github.com/elastic/kibana/issues/75862
|
// this type is based on BadRequest values observed while debugging https://github.com/elastic/kibana/issues/75862
|
||||||
|
|
||||||
const getHTTPResponseCode = (error: IngestManagerError): number => {
|
const getHTTPResponseCode = (error: IngestManagerError): number => {
|
||||||
if (error instanceof RegistryError) {
|
if (error instanceof RegistryResponseError) {
|
||||||
|
// 4xx/5xx's from EPR
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
if (error instanceof RegistryConnectionError || error instanceof RegistryError) {
|
||||||
|
// Connection errors (ie. RegistryConnectionError) / fallback (RegistryError) from EPR
|
||||||
return 502; // Bad Gateway
|
return 502; // Bad Gateway
|
||||||
}
|
}
|
||||||
if (error instanceof PackageNotFoundError) {
|
if (error instanceof PackageNotFoundError) {
|
||||||
|
|
Loading…
Reference in a new issue