[Fleet] Show the has upgrade button when ugprade is available (#147879)

This commit is contained in:
Nicolas Chaulet 2022-12-21 10:18:49 -05:00 committed by GitHub
parent fe872cc696
commit 390d22aae7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 131 additions and 119 deletions

View file

@ -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'] => [

View file

@ -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

View file

@ -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';

View file

@ -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();
});
});

View file

@ -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,
};
};

View file

@ -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,
};
};