Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fleet] Add package policy upgrade API #103017

Merged
merged 36 commits into from
Jul 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
a8c8d7f
Add Integrations page callout for package upgades
Zacqary Jun 4, 2021
4b0969e
Fix props
Zacqary Jun 4, 2021
6a1387a
Add missing file
Zacqary Jun 4, 2021
f76a5e9
Add integrations upgrade callout message
Zacqary Jun 7, 2021
cc10ba7
Add link to updates available tab
Zacqary Jun 8, 2021
82a78d1
Merge remote-tracking branch 'upstream/master' into 92612-policy-upgr…
Zacqary Jun 8, 2021
9fb216e
Fix merge
Zacqary Jun 8, 2021
b1b2380
Upgrade ppolicies UI WIP
Zacqary Jun 10, 2021
ab2804f
Merge remote-tracking branch 'upstream/master' into 92612-policy-upgr…
Zacqary Jun 14, 2021
1a881ce
Initial upgrade dry run API
Zacqary Jun 15, 2021
a3d0c9a
Add upgrade method
Zacqary Jun 16, 2021
50ea6a1
Merge remote-tracking branch 'upstream/master' into 92612-policy-upgr…
Zacqary Jun 21, 2021
523a3c8
Move overridePackageInputs and use for upgrade method
Zacqary Jun 21, 2021
5daede9
Add new variables to dry run diff
Zacqary Jun 22, 2021
1f8fffc
Merge remote-tracking branch 'upstream/master' into 92612-policy-upgr…
Zacqary Jun 22, 2021
9de37b6
Revert UI changes to uto upgrade wizard
Zacqary Jun 22, 2021
66fbfaf
Add vars and streams to error keys
Zacqary Jun 22, 2021
35337d1
Type fix
Zacqary Jun 23, 2021
8f16bb5
Fix jest
Zacqary Jun 23, 2021
1097144
Fix types
Zacqary Jun 23, 2021
d7de21b
Fix typecheck
Zacqary Jun 24, 2021
e4aa0de
Merge branch 'master' into 92612-policy-upgrade-wizard
kpollich Jul 19, 2021
888e26e
Fix types
kpollich Jul 19, 2021
2dc07d1
Add integration test for dry run API
kpollich Jul 20, 2021
93f5bda
Flesh out test cases
kpollich Jul 20, 2021
4e37e8d
Clean up error responses for dry runs
kpollich Jul 21, 2021
5bdce5a
Merge branch 'master' into 92612-policy-upgrade-wizard
kibanamachine Jul 21, 2021
cd01d7a
Fix failing tests
kpollich Jul 21, 2021
a344796
WIP: Add (failing for now) test case for package upgrade w/ error
kpollich Jul 26, 2021
eb97704
Add compiled_stream to test API payload
kpollich Jul 26, 2021
2347b1f
Merge branch 'master' into 92612-policy-upgrade-wizard
kpollich Jul 26, 2021
1274604
Fix failing test case for automatic upgrade
kpollich Jul 26, 2021
2eccd3a
Fix compiled stream in package policy upgrade
kpollich Jul 26, 2021
213d954
Merge branch 'master' into 92612-policy-upgrade-wizard
kibanamachine Jul 26, 2021
22b7bcf
Remove fleet and agent setup from integration test
kpollich Jul 27, 2021
d68071f
Unload esarchiver fixtures in api integration test
kpollich Jul 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/common/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const PACKAGE_POLICY_API_ROUTES = {
CREATE_PATTERN: `${PACKAGE_POLICY_API_ROOT}`,
UPDATE_PATTERN: `${PACKAGE_POLICY_API_ROOT}/{packagePolicyId}`,
DELETE_PATTERN: `${PACKAGE_POLICY_API_ROOT}/delete`,
UPGRADE_PATTERN: `${PACKAGE_POLICY_API_ROOT}/upgrade`,
};

// Agent policy API routes
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/fleet/common/types/models/package_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ export interface PackagePolicy extends Omit<NewPackagePolicy, 'inputs'> {
}

export type PackagePolicySOAttributes = Omit<PackagePolicy, 'id' | 'version'>;

export type DryRunPackagePolicy = NewPackagePolicy & {
errors?: Array<{ key: string | undefined; message: string }>;
};
25 changes: 24 additions & 1 deletion x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
* 2.0.
*/

import type { PackagePolicy, NewPackagePolicy, UpdatePackagePolicy } from '../models';
import type {
PackagePolicy,
NewPackagePolicy,
UpdatePackagePolicy,
DryRunPackagePolicy,
} from '../models';

export interface GetPackagePoliciesRequest {
query: {
Expand Down Expand Up @@ -57,3 +62,21 @@ export type DeletePackagePoliciesResponse = Array<{
name?: string;
success: boolean;
}>;

export interface UpgradePackagePolicyBaseResponse {
name?: string;
}

export interface UpgradePackagePolicyDryRunResponseItem extends UpgradePackagePolicyBaseResponse {
hasErrors: boolean;
diff?: [PackagePolicy, DryRunPackagePolicy];
}

export type UpgradePackagePolicyDryRunResponse = UpgradePackagePolicyDryRunResponseItem[];

export interface UpgradePackagePolicyResponseItem extends UpgradePackagePolicyBaseResponse {
id: string;
success: boolean;
}

export type UpgradePackagePolicyResponse = UpgradePackagePolicyResponseItem[];
84 changes: 84 additions & 0 deletions x-pack/plugins/fleet/public/hooks/use_package_installations.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* 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';

export const usePackageInstallations = () => {
const { data: allPackages, isLoading: isLoadingPackages } = useGetPackages({
experimental: true,
});

const { data: agentPolicyData, isLoading: isLoadingPolicies } = useGetAgentPolicies({
full: true,
});

const allInstalledPackages = useMemo(
() =>
(allPackages?.response || []).filter((pkg) => pkg.status === installationStatuses.Installed),
[allPackages?.response]
);

const updatablePackages = useMemo(
() =>
allInstalledPackages.filter(
(item) =>
'savedObject' in item && semverLt(item.savedObject.attributes.version, item.version)
),
[allInstalledPackages]
);

const updatableIntegrations = useMemo(
() =>
(agentPolicyData?.items || []).reduce((result, policy) => {
policy.package_policies.forEach((pkgPolicy: PackagePolicy | string) => {
if (typeof pkgPolicy === 'string' || !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,
pkgPolicyId: pkgPolicy.id,
pkgPolicyName: pkgPolicy.name,
pkgPolicyIntegrationVersion: version,
});
result.set(name, packageData);
}
});
return result;
}, new Map()),
[allInstalledPackages, agentPolicyData]
);

return {
allPackages,
allInstalledPackages,
updatablePackages,
updatableIntegrations,
isLoadingPackages,
isLoadingPolicies,
};
};
3 changes: 3 additions & 0 deletions x-pack/plugins/fleet/server/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ export const createPackagePolicyServiceMock = () => {
listIds: jest.fn(),
update: jest.fn(),
runExternalCallbacks: jest.fn(),
upgrade: jest.fn(),
getUpgradeDryRunDiff: jest.fn(),
getUpgradePackagePolicyInfo: jest.fn(),
} as jest.Mocked<PackagePolicyServiceInterface>;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ import type { CreatePackagePolicyRequestSchema } from '../../types/rest_spec';

import { registerRoutes } from './index';

type PackagePolicyServicePublicInterface = Omit<
PackagePolicyServiceInterface,
'getUpgradePackagePolicyInfo'
>;

const packagePolicyServiceMock = packagePolicyService as jest.Mocked<PackagePolicyServiceInterface>;

jest.mock('../../services/package_policy', (): {
packagePolicyService: jest.Mocked<PackagePolicyServiceInterface>;
packagePolicyService: jest.Mocked<PackagePolicyServicePublicInterface>;
} => {
return {
packagePolicyService: {
Expand Down Expand Up @@ -56,6 +61,8 @@ jest.mock('../../services/package_policy', (): {
runExternalCallbacks: jest.fn((callbackType, newPackagePolicy, context, request) =>
Promise.resolve(newPackagePolicy)
),
upgrade: jest.fn(),
getUpgradeDryRunDiff: jest.fn(),
},
};
});
Expand Down
43 changes: 42 additions & 1 deletion x-pack/plugins/fleet/server/routes/package_policy/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ import type {
CreatePackagePolicyRequestSchema,
UpdatePackagePolicyRequestSchema,
DeletePackagePoliciesRequestSchema,
UpgradePackagePoliciesRequestSchema,
} from '../../types';
import type { CreatePackagePolicyResponse, DeletePackagePoliciesResponse } from '../../../common';
import type {
CreatePackagePolicyResponse,
DeletePackagePoliciesResponse,
UpgradePackagePolicyDryRunResponse,
UpgradePackagePolicyResponse,
} from '../../../common';
import { defaultIngestErrorHandler } from '../../errors';

export const getPackagePoliciesHandler: RequestHandler<
Expand Down Expand Up @@ -172,3 +178,38 @@ export const deletePackagePolicyHandler: RequestHandler<
return defaultIngestErrorHandler({ error, response });
}
};

export const upgradePackagePolicyHandler: RequestHandler<
unknown,
unknown,
TypeOf<typeof UpgradePackagePoliciesRequestSchema.body>
> = async (context, request, response) => {
const soClient = context.core.savedObjects.client;
const esClient = context.core.elasticsearch.client.asCurrentUser;
const user = appContextService.getSecurity()?.authc.getCurrentUser(request) || undefined;
try {
if (request.body.dryRun) {
const body: UpgradePackagePolicyDryRunResponse = [];

for (const id of request.body.packagePolicyIds) {
const result = await packagePolicyService.getUpgradeDryRunDiff(soClient, id);
body.push(result);
}
return response.ok({
body,
});
} else {
const body: UpgradePackagePolicyResponse = await packagePolicyService.upgrade(
soClient,
esClient,
request.body.packagePolicyIds,
{ user }
);
return response.ok({
body,
});
}
} catch (error) {
return defaultIngestErrorHandler({ error, response });
}
};
12 changes: 12 additions & 0 deletions x-pack/plugins/fleet/server/routes/package_policy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
CreatePackagePolicyRequestSchema,
UpdatePackagePolicyRequestSchema,
DeletePackagePoliciesRequestSchema,
UpgradePackagePoliciesRequestSchema,
} from '../../types';

import {
Expand All @@ -22,6 +23,7 @@ import {
createPackagePolicyHandler,
updatePackagePolicyHandler,
deletePackagePolicyHandler,
upgradePackagePolicyHandler,
} from './handlers';

export const registerRoutes = (router: IRouter) => {
Expand Down Expand Up @@ -74,4 +76,14 @@ export const registerRoutes = (router: IRouter) => {
},
deletePackagePolicyHandler
);

// Upgrade
router.post(
{
path: PACKAGE_POLICY_API_ROUTES.UPGRADE_PATTERN,
validate: UpgradePackagePoliciesRequestSchema,
options: { tags: [`access:${PLUGIN_ID}-all`] },
},
upgradePackagePolicyHandler
);
};
Loading