mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Fleet] Show the has upgrade button when ugprade is available (#147879)
This commit is contained in:
parent
fe872cc696
commit
390d22aae7
6 changed files with 131 additions and 119 deletions
|
@ -32,7 +32,7 @@ import {
|
|||
import {
|
||||
useAuthz,
|
||||
useLink,
|
||||
usePackageInstallations,
|
||||
useIsPackagePolicyUpgradable,
|
||||
usePermissionCheck,
|
||||
useStartServices,
|
||||
} from '../../../../../hooks';
|
||||
|
@ -62,7 +62,7 @@ export const PackagePoliciesTable: React.FunctionComponent<Props> = ({
|
|||
const { application } = useStartServices();
|
||||
const canWriteIntegrationPolicies = useAuthz().integrations.writeIntegrationPolicies;
|
||||
const canReadIntegrationPolicies = useAuthz().integrations.readIntegrationPolicies;
|
||||
const { updatableIntegrations } = usePackageInstallations();
|
||||
const { isPackagePolicyUpgradable } = useIsPackagePolicyUpgradable();
|
||||
const { getHref } = useLink();
|
||||
|
||||
const permissionCheck = usePermissionCheck();
|
||||
|
@ -80,15 +80,7 @@ export const PackagePoliciesTable: React.FunctionComponent<Props> = ({
|
|||
namespacesValues.add(packagePolicy.namespace);
|
||||
}
|
||||
|
||||
const updatableIntegrationRecord = updatableIntegrations.get(
|
||||
packagePolicy.package?.name ?? ''
|
||||
);
|
||||
|
||||
const hasUpgrade =
|
||||
!!updatableIntegrationRecord &&
|
||||
updatableIntegrationRecord.policiesToUpgrade.some(
|
||||
({ pkgPolicyId }) => pkgPolicyId === packagePolicy.id
|
||||
);
|
||||
const hasUpgrade = isPackagePolicyUpgradable(packagePolicy);
|
||||
|
||||
return {
|
||||
...packagePolicy,
|
||||
|
@ -105,7 +97,7 @@ export const PackagePoliciesTable: React.FunctionComponent<Props> = ({
|
|||
.map(toFilterOption);
|
||||
|
||||
return [mappedPackagePolicies, namespaceFilterOptions];
|
||||
}, [originalPackagePolicies, updatableIntegrations]);
|
||||
}, [originalPackagePolicies, isPackagePolicyUpgradable]);
|
||||
|
||||
const columns = useMemo(
|
||||
(): EuiInMemoryTableProps<InMemoryPackagePolicy>['columns'] => [
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
useUrlPagination,
|
||||
useGetPackageInstallStatus,
|
||||
AgentPolicyRefreshContext,
|
||||
usePackageInstallations,
|
||||
useIsPackagePolicyUpgradable,
|
||||
useAuthz,
|
||||
} from '../../../../../hooks';
|
||||
import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../../constants';
|
||||
|
@ -108,7 +108,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
|
|||
perPage: pagination.pageSize,
|
||||
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: ${name}`,
|
||||
});
|
||||
const { updatableIntegrations } = usePackageInstallations();
|
||||
const { isPackagePolicyUpgradable } = useIsPackagePolicyUpgradable();
|
||||
|
||||
const canWriteIntegrationPolicies = useAuthz().integrations.writeIntegrationPolicies;
|
||||
|
||||
|
@ -121,14 +121,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
|
|||
}
|
||||
|
||||
const newPolicies = data.items.map(({ agentPolicy, packagePolicy }) => {
|
||||
const updatableIntegrationRecord = updatableIntegrations.get(
|
||||
packagePolicy.package?.name ?? ''
|
||||
);
|
||||
const hasUpgrade =
|
||||
!!updatableIntegrationRecord &&
|
||||
updatableIntegrationRecord.policiesToUpgrade.some(
|
||||
({ pkgPolicyId }) => pkgPolicyId === packagePolicy.id
|
||||
);
|
||||
const hasUpgrade = isPackagePolicyUpgradable(packagePolicy);
|
||||
|
||||
return {
|
||||
agentPolicy,
|
||||
|
@ -140,7 +133,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps
|
|||
});
|
||||
|
||||
return newPolicies;
|
||||
}, [data?.items, updatableIntegrations]);
|
||||
}, [data?.items, isPackagePolicyUpgradable]);
|
||||
|
||||
const showAddAgentHelpForPackagePolicyId = packageAndAgentPolicies.find(
|
||||
({ agentPolicy }) => agentPolicy?.id === showAddAgentHelpForPolicyId
|
||||
|
|
|
@ -25,7 +25,7 @@ export * from './use_ui_extension';
|
|||
export * from './use_intra_app_state';
|
||||
export * from './use_platform';
|
||||
export * from './use_agent_policy_refresh';
|
||||
export * from './use_package_installations';
|
||||
export * from './use_is_package_policy_upgradable';
|
||||
export * from './use_agent_enrollment_flyout_data';
|
||||
export * from './use_flyout_context';
|
||||
export * from './use_is_guided_onboarding_active';
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 { renderHook } from '@testing-library/react-hooks';
|
||||
|
||||
import { useIsPackagePolicyUpgradable } from './use_is_package_policy_upgradable';
|
||||
import { useGetPackages } from './use_request/epm';
|
||||
|
||||
jest.mock('./use_request/epm');
|
||||
|
||||
const mockedUseGetPackages = useGetPackages as jest.MockedFunction<typeof useGetPackages>;
|
||||
|
||||
describe('useIsPackagePolicyUpgradable', () => {
|
||||
beforeEach(() => {
|
||||
mockedUseGetPackages.mockReturnValue({
|
||||
error: null,
|
||||
isInitialRequest: false,
|
||||
isLoading: false,
|
||||
data: {
|
||||
items: [
|
||||
{
|
||||
status: 'installed',
|
||||
savedObject: {
|
||||
attributes: {
|
||||
name: 'test',
|
||||
version: '1.0.0',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} as any);
|
||||
});
|
||||
it('should return true with an upgradable package policy', () => {
|
||||
const { result } = renderHook(() => useIsPackagePolicyUpgradable());
|
||||
const isUpgradable = result.current.isPackagePolicyUpgradable({
|
||||
package: {
|
||||
name: 'test',
|
||||
version: '0.9.0',
|
||||
},
|
||||
} as any);
|
||||
expect(isUpgradable).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false with a non upgradable package policy', () => {
|
||||
const { result } = renderHook(() => useIsPackagePolicyUpgradable());
|
||||
const isUpgradable = result.current.isPackagePolicyUpgradable({
|
||||
package: {
|
||||
name: 'test',
|
||||
version: '1.0.0',
|
||||
},
|
||||
} as any);
|
||||
expect(isUpgradable).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false with a non installed package', () => {
|
||||
const { result } = renderHook(() => useIsPackagePolicyUpgradable());
|
||||
const isUpgradable = result.current.isPackagePolicyUpgradable({
|
||||
package: {
|
||||
name: 'idonotexists',
|
||||
version: '1.0.0',
|
||||
},
|
||||
} as any);
|
||||
expect(isUpgradable).toBeFalsy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 { useCallback, useMemo } from 'react';
|
||||
import semverLt from 'semver/functions/lt';
|
||||
|
||||
import { installationStatuses } from '../../common/constants';
|
||||
import type { PackagePolicy } from '../types';
|
||||
|
||||
import { useGetPackages } from './use_request/epm';
|
||||
|
||||
export const useIsPackagePolicyUpgradable = () => {
|
||||
const { data: allPackages, isLoading: isLoadingPackages } = useGetPackages({
|
||||
prerelease: true,
|
||||
});
|
||||
|
||||
const allInstalledPackages = useMemo(
|
||||
() => (allPackages?.items || []).filter((pkg) => pkg.status === installationStatuses.Installed),
|
||||
[allPackages?.items]
|
||||
);
|
||||
|
||||
const isPackagePolicyUpgradable = useCallback(
|
||||
(pkgPolicy: PackagePolicy) => {
|
||||
if (!pkgPolicy.package) {
|
||||
return false;
|
||||
}
|
||||
const { name, version } = pkgPolicy.package;
|
||||
const installedPackage = allInstalledPackages.find(
|
||||
(installedPkg) =>
|
||||
'savedObject' in installedPkg && installedPkg.savedObject.attributes.name === name
|
||||
);
|
||||
if (
|
||||
installedPackage &&
|
||||
'savedObject' in installedPackage &&
|
||||
semverLt(version, installedPackage.savedObject.attributes.version)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[allInstalledPackages]
|
||||
);
|
||||
|
||||
return {
|
||||
isPackagePolicyUpgradable,
|
||||
isLoadingPackages,
|
||||
};
|
||||
};
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* 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 { useMemo } from 'react';
|
||||
import semverLt from 'semver/functions/lt';
|
||||
|
||||
import { installationStatuses } from '../../common/constants';
|
||||
import type { PackagePolicy } from '../types';
|
||||
|
||||
import { useGetPackages } from './use_request/epm';
|
||||
import { useGetAgentPolicies } from './use_request/agent_policy';
|
||||
|
||||
interface UpdatableIntegration {
|
||||
currentVersion: string;
|
||||
policiesToUpgrade: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
agentsCount: number;
|
||||
pkgPolicyId: string;
|
||||
pkgPolicyName: string;
|
||||
pkgPolicyIntegrationVersion: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export const usePackageInstallations = () => {
|
||||
const { data: allPackages, isLoading: isLoadingPackages } = useGetPackages({
|
||||
prerelease: true,
|
||||
});
|
||||
|
||||
const { data: agentPolicyData, isLoading: isLoadingPolicies } = useGetAgentPolicies({
|
||||
full: true,
|
||||
});
|
||||
|
||||
const allInstalledPackages = useMemo(
|
||||
() => (allPackages?.items || []).filter((pkg) => pkg.status === installationStatuses.Installed),
|
||||
[allPackages?.items]
|
||||
);
|
||||
|
||||
const updatablePackages = useMemo(
|
||||
() =>
|
||||
allInstalledPackages.filter(
|
||||
(item) =>
|
||||
'savedObject' in item && semverLt(item.savedObject.attributes.version, item.version)
|
||||
),
|
||||
[allInstalledPackages]
|
||||
);
|
||||
|
||||
const updatableIntegrations = useMemo<Map<string, UpdatableIntegration>>(
|
||||
() =>
|
||||
(agentPolicyData?.items || []).reduce((result, policy) => {
|
||||
policy.package_policies?.forEach((pkgPolicy: PackagePolicy) => {
|
||||
if (!pkgPolicy.package) return false;
|
||||
const { name, version } = pkgPolicy.package;
|
||||
const installedPackage = allInstalledPackages.find(
|
||||
(installedPkg) =>
|
||||
'savedObject' in installedPkg && installedPkg.savedObject.attributes.name === name
|
||||
);
|
||||
if (
|
||||
installedPackage &&
|
||||
'savedObject' in installedPackage &&
|
||||
semverLt(version, installedPackage.savedObject.attributes.version)
|
||||
) {
|
||||
const packageData = result.get(name) ?? {
|
||||
currentVersion: installedPackage.savedObject.attributes.version,
|
||||
policiesToUpgrade: [],
|
||||
};
|
||||
packageData.policiesToUpgrade.push({
|
||||
id: policy.id,
|
||||
name: policy.name,
|
||||
agentsCount: policy.agents ?? 0,
|
||||
pkgPolicyId: pkgPolicy.id,
|
||||
pkgPolicyName: pkgPolicy.name,
|
||||
pkgPolicyIntegrationVersion: version,
|
||||
});
|
||||
result.set(name, packageData);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}, new Map<string, UpdatableIntegration>()),
|
||||
[allInstalledPackages, agentPolicyData]
|
||||
);
|
||||
|
||||
return {
|
||||
allPackages,
|
||||
allInstalledPackages,
|
||||
updatablePackages,
|
||||
updatableIntegrations,
|
||||
isLoadingPackages,
|
||||
isLoadingPolicies,
|
||||
};
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue