Skip to content

Commit

Permalink
[Dataset Quality] Change logic to identify integrations (elastic#198692)
Browse files Browse the repository at this point in the history
Co-authored-by: kibanamachine <[email protected]>
Co-authored-by: Elastic Machine <[email protected]>
Co-authored-by: Felix Stürmer <[email protected]>
  • Loading branch information
4 people authored Dec 2, 2024
1 parent 281269f commit 86a0444
Show file tree
Hide file tree
Showing 44 changed files with 1,019 additions and 320 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ export function DatasetQualityDetailsContextProvider({
urlStateStorageContainer,
datasetQualityDetailsState: state,
});
const breadcrumbValue = getBreadcrumbValue(state.dataStream, state.integration);
const breadcrumbValue = getBreadcrumbValue(
state.dataStream,
state.integration?.integration
);
setBreadcrumbs([{ text: breadcrumbValue }]);
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const createClientMock = (): jest.Mocked<PackageClient> => ({
fetchFindLatestPackage: jest.fn(),
readBundledPackage: jest.fn(),
getAgentPolicyConfigYAML: jest.fn(),
getLatestPackageInfo: jest.fn(),
getPackage: jest.fn(),
getPackageFieldsMetadata: jest.fn(),
getPackages: jest.fn(),
Expand Down
24 changes: 21 additions & 3 deletions x-pack/plugins/fleet/server/services/epm/package_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const testKeys = [
'getInstallation',
'ensureInstalledPackage',
'fetchFindLatestPackage',
'getLatestPackageInfo',
'getPackage',
'getPackageFieldsMetadata',
'reinstallEsAssets',
Expand Down Expand Up @@ -112,6 +113,23 @@ function getTest(
};
break;
case testKeys[3]:
test = {
method: mocks.packageClient.getLatestPackageInfo.bind(mocks.packageClient),
args: ['package name'],
spy: jest.spyOn(epmPackagesGet, 'getPackageInfo'),
spyArgs: [
{
pkgName: 'package name',
pkgVersion: '',
savedObjectsClient: mocks.soClient,
prerelease: undefined,
},
],
spyResponse: { name: 'getLatestPackageInfo test' },
expectedReturnValue: { name: 'getLatestPackageInfo test' },
};
break;
case testKeys[4]:
test = {
method: mocks.packageClient.getPackage.bind(mocks.packageClient),
args: ['package name', '8.0.0'],
Expand All @@ -127,7 +145,7 @@ function getTest(
},
};
break;
case testKeys[4]:
case testKeys[5]:
test = {
method: mocks.packageClient.getPackageFieldsMetadata.bind(mocks.packageClient),
args: [{ packageName: 'package_name', datasetName: 'dataset_name' }],
Expand All @@ -141,7 +159,7 @@ function getTest(
},
};
break;
case testKeys[5]:
case testKeys[6]:
const pkg: InstallablePackage = {
format_version: '1.0.0',
name: 'package name',
Expand Down Expand Up @@ -187,7 +205,7 @@ function getTest(
],
};
break;
case testKeys[6]:
case testKeys[7]:
const bundledPackage = {
name: 'package name',
version: '8.0.0',
Expand Down
16 changes: 16 additions & 0 deletions x-pack/plugins/fleet/server/services/epm/package_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import {
getPackages,
installPackage,
getTemplateInputs,
getPackageInfo,
} from './packages';
import { generatePackageInfoFromArchiveBuffer } from './archive';
import { getEsPackage } from './archive/storage';
Expand Down Expand Up @@ -113,6 +114,11 @@ export interface PackageClient {
options?: Parameters<typeof getPackageFieldsMetadata>['1']
): ReturnType<typeof getPackageFieldsMetadata>;

getLatestPackageInfo(
packageName: string,
prerelease?: boolean
): ReturnType<typeof getPackageInfo>;

getPackages(params?: {
excludeInstallStatus?: false;
category?: CategoryId;
Expand Down Expand Up @@ -328,6 +334,16 @@ class PackageClientImpl implements PackageClient {
return getPackageFieldsMetadata(params, options);
}

public async getLatestPackageInfo(packageName: string, prerelease?: boolean) {
await this.#runPreflight(READ_PACKAGE_INFO_AUTHZ);
return getPackageInfo({
savedObjectsClient: this.internalSoClient,
pkgName: packageName,
pkgVersion: '',
prerelease,
});
}

public async getPackages(params?: {
excludeInstallStatus?: false;
category?: CategoryId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,24 @@ export const integrationRt = rt.intersection([

export type IntegrationType = rt.TypeOf<typeof integrationRt>;

export const checkAndLoadIntegrationResponseRt = rt.union([
rt.type({ isIntegration: rt.literal(false), areAssetsAvailable: rt.boolean }),
rt.type({
isIntegration: rt.literal(true),
areAssetsAvailable: rt.literal(true),
integration: integrationRt,
}),
]);

export type CheckAndLoadIntegrationResponse = rt.TypeOf<typeof checkAndLoadIntegrationResponseRt>;

export const getIntegrationsResponseRt = rt.exact(
rt.type({
integrations: rt.array(integrationRt),
})
);

export type IntegrationResponse = rt.TypeOf<typeof getIntegrationsResponseRt>;
export type IntegrationsResponse = rt.TypeOf<typeof getIntegrationsResponseRt>;

export const degradedFieldRt = rt.type({
name: rt.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
* 2.0.
*/

export interface GetDataStreamIntegrationParams {
integrationName: string;
}
import { Integration } from '../data_streams_stats/integration';

export interface AnalyzeDegradedFieldsParams {
dataStream: string;
Expand All @@ -19,3 +17,13 @@ export interface UpdateFieldLimitParams {
dataStream: string;
newFieldLimit: number;
}

export interface CheckAndLoadIntegrationParams {
dataStream: string;
}

export interface IntegrationType {
isIntegration: boolean;
areAssetsAvailable: boolean;
integration?: Integration;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ import { IncreaseFieldMappingLimit } from './increase_field_mapping_limit';
import { FieldLimitDocLink } from './field_limit_documentation_link';
import { MessageCallout } from './message_callout';

export function FieldMappingLimit({ isIntegration }: { isIntegration: boolean }) {
export function FieldMappingLimit({
areIntegrationAssetsAvailable,
}: {
areIntegrationAssetsAvailable: boolean;
}) {
const accordionId = useGeneratedHtmlId({
prefix: increaseFieldMappingLimitTitle,
});
Expand Down Expand Up @@ -66,7 +70,7 @@ export function FieldMappingLimit({ isIntegration }: { isIntegration: boolean })
</ul>
</EuiText>
<EuiHorizontalRule margin="s" />
{isIntegration && (
{areIntegrationAssetsAvailable && (
<>
<IncreaseFieldMappingLimit
totalFieldLimit={degradedFieldAnalysis?.totalFieldLimit ?? 0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function IncreaseFieldMappingLimit({ totalFieldLimit }: { totalFieldLimit
<EuiFlexItem grow={false}>
<EuiFormRow hasEmptyLabelSpace>
<EuiButton
data-test-subj="datasetQualityIncreaseFieldMappingLimitButtonButton"
data-test-subj="datasetQualityIncreaseFieldMappingLimitButton"
disabled={isInvalid}
onClick={() => updateNewFieldLimit(newFieldLimit)}
isLoading={isMitigationInProgress}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { PossibleMitigationTitle } from './title';
export function PossibleMitigations() {
const { degradedFieldAnalysis, isAnalysisInProgress } = useDegradedFields();
const { integrationDetails } = useDatasetQualityDetailsState();
const isIntegration = Boolean(integrationDetails?.integration);
const areIntegrationAssetsAvailable = !!integrationDetails?.integration?.areAssetsAvailable;

return (
!isAnalysisInProgress && (
Expand All @@ -24,7 +24,7 @@ export function PossibleMitigations() {
<EuiSpacer size="m" />
{degradedFieldAnalysis?.isFieldLimitIssue && (
<>
<FieldMappingLimit isIntegration={isIntegration} />
<FieldMappingLimit areIntegrationAssetsAvailable={areIntegrationAssetsAvailable} />
<EuiSpacer size="m" />
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import { useDatasetQualityDetailsState } from '../../../../../hooks';
import { getComponentTemplatePrefixFromIndexTemplate } from '../../../../../../common/utils/component_template_name';
import { otherMitigationsCustomComponentTemplate } from '../../../../../../common/translations';

export function CreateEditComponentTemplateLink({ isIntegration }: { isIntegration: boolean }) {
export function CreateEditComponentTemplateLink({
areIntegrationAssetsAvailable,
}: {
areIntegrationAssetsAvailable: boolean;
}) {
const {
services: {
application,
Expand Down Expand Up @@ -54,7 +58,7 @@ export function CreateEditComponentTemplateLink({ isIntegration }: { isIntegrati
name,
]);

const templateUrl = isIntegration ? componentTemplatePath : indexTemplatePath;
const templateUrl = areIntegrationAssetsAvailable ? componentTemplatePath : indexTemplatePath;

const onClickHandler = useCallback(async () => {
const options = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,27 @@ import { CreateEditPipelineLink } from './pipeline_link';
import { otherMitigationsLoadingAriaText } from '../../../../../../common/translations';

export function ManualMitigations() {
const { integrationDetails, loadingState, dataStreamSettings } = useDatasetQualityDetailsState();
const isIntegrationPresentInSettings = dataStreamSettings?.integration;
const isIntegration = !!integrationDetails?.integration;
const { dataStreamSettingsLoading, integrationDetailsLoadings } = loadingState;

const hasIntegrationCheckCompleted =
!dataStreamSettingsLoading &&
((isIntegrationPresentInSettings && !integrationDetailsLoadings) ||
!isIntegrationPresentInSettings);
const {
integrationDetails,
loadingState: { integrationDetailsLoaded },
} = useDatasetQualityDetailsState();
const areIntegrationAssetsAvailable = !!integrationDetails?.integration?.areAssetsAvailable;

return (
<EuiSkeletonRectangle
isLoading={!hasIntegrationCheckCompleted}
isLoading={!integrationDetailsLoaded}
contentAriaLabel={otherMitigationsLoadingAriaText}
width="100%"
height={300}
borderRadius="none"
data-test-subj="datasetQualityDetailsFlyoutManualMitigationsLoading"
className="datasetQualityDetailsFlyoutManualMitigationsLoading"
>
<CreateEditComponentTemplateLink isIntegration={isIntegration} />
<CreateEditComponentTemplateLink
areIntegrationAssetsAvailable={areIntegrationAssetsAvailable}
/>
<EuiSpacer size="s" />
<CreateEditPipelineLink isIntegration={isIntegration} />
<CreateEditPipelineLink areIntegrationAssetsAvailable={areIntegrationAssetsAvailable} />
</EuiSkeletonRectangle>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useCallback, useMemo } from 'react';
import React, { useCallback } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import {
Expand Down Expand Up @@ -34,7 +34,11 @@ const AccordionTitle = () => (
</EuiTitle>
);

export function CreateEditPipelineLink({ isIntegration }: { isIntegration: boolean }) {
export function CreateEditPipelineLink({
areIntegrationAssetsAvailable,
}: {
areIntegrationAssetsAvailable: boolean;
}) {
const {
services: {
share: {
Expand All @@ -50,10 +54,7 @@ export function CreateEditPipelineLink({ isIntegration }: { isIntegration: boole
const { datasetDetails } = useDatasetQualityDetailsState();
const { type, name } = datasetDetails;

const pipelineName = useMemo(
() => (isIntegration ? `${type}-${name}@custom` : `${type}@custom`),
[isIntegration, type, name]
);
const pipelineName = areIntegrationAssetsAvailable ? `${type}-${name}@custom` : `${type}@custom`;

const ingestPipelineLocator = locators.get('INGEST_PIPELINES_APP_LOCATOR');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import React, { Fragment } from 'react';
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types';
import { EuiBadge, EuiFlexGroup, EuiPanel, EuiText } from '@elastic/eui';
import { EuiBadge, EuiFlexGroup, EuiPanel, EuiSkeletonRectangle, EuiText } from '@elastic/eui';
import { css } from '@emotion/react';
import { IntegrationActionsMenu } from './integration_actions_menu';
import {
Expand All @@ -29,7 +29,8 @@ export function DatasetSummary() {
const {
dataStreamDetailsLoading,
dataStreamSettingsLoading,
integrationDetailsLoadings,
integrationDetailsLoading,
integrationDetailsLoaded,
integrationDashboardsLoading,
} = loadingState;
const formattedLastActivity = dataStreamDetails?.lastActivity
Expand All @@ -39,12 +40,19 @@ export function DatasetSummary() {
? dataFormatter.convert(dataStreamSettings.createdOn)
: '-';

return (
return !integrationDetailsLoaded ? (
<EuiSkeletonRectangle
width="100%"
height="200px"
data-test-subj="datasetQualityDetailsDetailsSectionLoading"
className="datasetQualityDetailsDetailsSectionLoading"
/>
) : (
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="none">
<Fragment>
<FieldsList
fields={[
...(integrationDetails?.integration
...(integrationDetails?.integration?.integration
? [
{
fieldTitle: integrationNameText,
Expand All @@ -56,24 +64,28 @@ export function DatasetSummary() {
`}
>
<EuiFlexGroup gutterSize="xs" alignItems="center">
<IntegrationIcon integration={integrationDetails.integration} />
<EuiText size="s">{integrationDetails.integration?.name}</EuiText>
<IntegrationIcon
integration={integrationDetails.integration.integration}
/>
<EuiText size="s">
{integrationDetails.integration.integration?.name}
</EuiText>
</EuiFlexGroup>
</EuiBadge>
),
actionsMenu: (
<IntegrationActionsMenu
integration={integrationDetails.integration}
integration={integrationDetails.integration.integration}
dashboards={integrationDetails.dashboard}
dashboardsLoading={integrationDashboardsLoading}
/>
),
isLoading: integrationDetailsLoadings,
isLoading: integrationDetailsLoading,
},
{
fieldTitle: integrationVersionText,
fieldValue: integrationDetails.integration?.version,
isLoading: integrationDetailsLoadings,
fieldValue: integrationDetails.integration.integration?.version,
isLoading: integrationDetailsLoading,
},
]
: []),
Expand Down
Loading

0 comments on commit 86a0444

Please sign in to comment.