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] Support Input Packages #140035

Merged
merged 26 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3f4a8cf
seperate types for integration and input packages
hop-dev Aug 16, 2022
10d2a41
Simplify input only package types
hop-dev Aug 17, 2022
be3879b
add util for checking policy template type
hop-dev Aug 17, 2022
1b03dd2
fix type errors now there are 2 kinds of policy template
hop-dev Aug 17, 2022
08ecb5a
Package policies being generate for input packages
hop-dev Aug 18, 2022
b311b3d
fix types
hop-dev Sep 5, 2022
e55caee
support input templates
hop-dev Sep 6, 2022
550b3cc
neaten for PR
hop-dev Sep 7, 2022
580ebb3
more PR tidy
hop-dev Sep 7, 2022
ada7f12
dont show input disbale switch for input only policies
hop-dev Sep 7, 2022
dca8301
always read input only pkg info from the archive
hop-dev Sep 8, 2022
ccfbd47
fix limited package check
hop-dev Sep 9, 2022
77116b1
use negative check
hop-dev Sep 9, 2022
f229a77
add unit tests
hop-dev Sep 9, 2022
a71003d
fix isIntegrationPolicyTemplate
hop-dev Sep 9, 2022
f51bb21
generate index permissions
hop-dev Sep 12, 2022
a52ea39
do not use template for input
hop-dev Sep 12, 2022
aa9e602
fix types
hop-dev Sep 12, 2022
12ffa6c
Merge branch 'main' into 137750-support-input-pkgs
kibanamachine Sep 12, 2022
f022f17
fix tests
hop-dev Sep 12, 2022
1aea9c2
Merge branch '137750-support-input-pkgs' of github.com:hop-dev/kibana…
hop-dev Sep 12, 2022
c21993d
Merge branch 'main' into 137750-support-input-pkgs
hop-dev Sep 12, 2022
8205d63
dont shwo description for input packages
hop-dev Sep 13, 2022
a0aac92
Merge branch 'main' into 137750-support-input-pkgs
hop-dev Sep 13, 2022
b228d5e
flip flag
hop-dev Sep 14, 2022
d7c9cf2
Merge branch 'main' into 137750-support-input-pkgs
hop-dev Sep 14, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export async function getLatestApmPackage({
const registryPackage = await packageClient.getRegistryPackage(name, version);
const { title, policy_templates: policyTemplates } =
registryPackage.packageInfo;
const policyTemplateInputVars = policyTemplates?.[0].inputs?.[0].vars ?? [];
const firstTemplate = policyTemplates?.[0];
const policyTemplateInputVars =
firstTemplate && 'inputs' in firstTemplate
? firstTemplate.inputs?.[0].vars || []
: [];
return { package: { name, version, title }, policyTemplateInputVars };
}
6 changes: 6 additions & 0 deletions x-pack/plugins/fleet/common/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ export { isValidNamespace } from './is_valid_namespace';
export { isDiffPathProtocol } from './is_diff_path_protocol';
export { LicenseService } from './license';
export { isAgentUpgradeable } from './is_agent_upgradeable';
export {
isInputOnlyPolicyTemplate,
isIntegrationPolicyTemplate,
getNormalizedInputs,
getNormalizedDataStreams,
} from './policy_template';
export { doesPackageHaveIntegrations } from './packages_with_integrations';
export type {
PackagePolicyValidationResults,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ import type {
} from '../types';

import { doesPackageHaveIntegrations } from '.';
import {
getNormalizedDataStreams,
getNormalizedInputs,
isIntegrationPolicyTemplate,
} from './policy_template';

type PackagePolicyStream = RegistryStream & { release?: 'beta' | 'experimental' | 'ga' } & {
data_stream: { type: string; dataset: string };
Expand All @@ -29,7 +34,7 @@ export const getStreamsForInputType = (
dataStreamPaths: string[] = []
): PackagePolicyStream[] => {
const streams: PackagePolicyStream[] = [];
const dataStreams = packageInfo.data_streams || [];
const dataStreams = getNormalizedDataStreams(packageInfo);
const dataStreamsToSearch = dataStreamPaths.length
? dataStreams.filter((dataStream) => dataStreamPaths.includes(dataStream.path))
: dataStreams;
Expand Down Expand Up @@ -81,11 +86,12 @@ export const packageToPackagePolicyInputs = (
} = {};

packageInfo.policy_templates?.forEach((packagePolicyTemplate) => {
packagePolicyTemplate.inputs?.forEach((packageInput) => {
const normalizedInputs = getNormalizedInputs(packagePolicyTemplate);
normalizedInputs?.forEach((packageInput) => {
const inputKey = `${packagePolicyTemplate.name}-${packageInput.type}`;
const input = {
...packageInput,
...(packagePolicyTemplate.data_streams
...(isIntegrationPolicyTemplate(packagePolicyTemplate) && packagePolicyTemplate.data_streams
? { data_streams: packagePolicyTemplate.data_streams }
: {}),
policy_template: packagePolicyTemplate.name,
Expand Down
278 changes: 278 additions & 0 deletions x-pack/plugins/fleet/common/services/policy_template.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
/*
* 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 type {
RegistryPolicyInputOnlyTemplate,
RegistryPolicyIntegrationTemplate,
PackageInfo,
RegistryVarType,
} from '../types';

import {
isInputOnlyPolicyTemplate,
isIntegrationPolicyTemplate,
getNormalizedInputs,
getNormalizedDataStreams,
} from './policy_template';

describe('isInputOnlyPolicyTemplate', () => {
it('should return true input only policy template', () => {
const inputOnlyPolicyTemplate: RegistryPolicyInputOnlyTemplate = {
input: 'string',
type: 'foo',
name: 'bar',
template_path: 'some/path.hbl',
title: 'hello',
description: 'desc',
};
expect(isInputOnlyPolicyTemplate(inputOnlyPolicyTemplate)).toEqual(true);
});
it('should return false for empty integration policy template', () => {
const emptyIntegrationTemplate: RegistryPolicyIntegrationTemplate = {
inputs: [],
name: 'bar',
title: 'hello',
description: 'desc',
};
expect(isInputOnlyPolicyTemplate(emptyIntegrationTemplate)).toEqual(false);
});
it('should return false for integration policy template with inputs', () => {
const integrationTemplate: RegistryPolicyIntegrationTemplate = {
inputs: [
{
type: 'foo',
title: 'myFoo',
description: 'myFoo',
vars: [],
},
],
name: 'bar',
title: 'hello',
description: 'desc',
};
expect(isInputOnlyPolicyTemplate(integrationTemplate)).toEqual(false);
});
});
describe('isIntegrationPolicyTemplate', () => {
it('should return true input only policy template', () => {
const inputOnlyPolicyTemplate: RegistryPolicyInputOnlyTemplate = {
input: 'string',
type: 'foo',
name: 'bar',
template_path: 'some/path.hbl',
title: 'hello',
description: 'desc',
};
expect(isIntegrationPolicyTemplate(inputOnlyPolicyTemplate)).toEqual(false);
});
it('should return false for empty integration policy template', () => {
const emptyIntegrationTemplate: RegistryPolicyIntegrationTemplate = {
inputs: [],
name: 'bar',
title: 'hello',
description: 'desc',
};
expect(isIntegrationPolicyTemplate(emptyIntegrationTemplate)).toEqual(true);
});
it('should return false for integration policy template with inputs', () => {
const integrationTemplate: RegistryPolicyIntegrationTemplate = {
inputs: [
{
type: 'foo',
title: 'myFoo',
description: 'myFoo',
vars: [],
},
],
name: 'bar',
title: 'hello',
description: 'desc',
};
expect(isIntegrationPolicyTemplate(integrationTemplate)).toEqual(true);
});
});

describe('getNormalizedInputs', () => {
it('should return empty array if template has no inputs', () => {
const emptyIntegrationTemplate: RegistryPolicyIntegrationTemplate = {
inputs: [],
name: 'bar',
title: 'hello',
description: 'desc',
};

expect(getNormalizedInputs(emptyIntegrationTemplate)).toEqual([]);
});
it('should return inputs if there are any', () => {
const emptyIntegrationTemplate: RegistryPolicyIntegrationTemplate = {
inputs: [
{
type: 'foo',
title: 'myFoo',
description: 'myFoo',
vars: [],
},
],
name: 'bar',
title: 'hello',
description: 'desc',
};

expect(getNormalizedInputs(emptyIntegrationTemplate)).toEqual([
{
type: 'foo',
title: 'myFoo',
description: 'myFoo',
vars: [],
},
]);
});
it('should return array with one input for input only', () => {
const inputOnlyTemplate: RegistryPolicyInputOnlyTemplate = {
input: 'string',
type: 'foo',
name: 'bar',
template_path: 'some/path.hbl',
title: 'myFoo',
description: 'myFoo',
};

expect(getNormalizedInputs(inputOnlyTemplate)).toEqual([
{
type: 'string',
title: 'myFoo',
description: 'myFoo',
},
]);
});
});

describe('getNormalizedDataStreams', () => {
const integrationPkg: PackageInfo = {
name: 'nginx',
title: 'Nginx',
version: '1.3.0',
release: 'ga',
description: 'Collect logs and metrics from Nginx HTTP servers with Elastic Agent.',
format_version: '',
owner: { github: '' },
assets: {} as any,
policy_templates: [],
data_streams: [
{
type: 'logs',
dataset: 'nginx.access',
title: 'Nginx access logs',
release: 'experimental',
ingest_pipeline: 'default',
streams: [
{
input: 'logfile',
vars: [
{
name: 'paths',
type: 'text',
title: 'Paths',
multi: true,
required: true,
show_user: true,
default: ['/var/log/nginx/access.log*'],
},
],
template_path: 'stream.yml.hbs',
title: 'Nginx access logs',
description: 'Collect Nginx access logs',
enabled: true,
},
],
package: 'nginx',
path: 'access',
},
],
latestVersion: '1.3.0',
keepPoliciesUpToDate: false,
status: 'not_installed',
};
it('should return data_streams for integration package', () => {
expect(getNormalizedDataStreams(integrationPkg)).toEqual(integrationPkg.data_streams);
});
it('should return data_streams for integration package with type specified', () => {
expect(getNormalizedDataStreams({ ...integrationPkg, type: 'integration' })).toEqual(
integrationPkg.data_streams
);
});
it('should return data_streams for empty integration package', () => {
expect(getNormalizedDataStreams({ ...integrationPkg, data_streams: [] })).toEqual([]);
});
it('should build data streams for input only package', () => {
expect(
getNormalizedDataStreams({
...integrationPkg,
type: 'input',
policy_templates: [
{
input: 'string',
type: 'foo',
name: 'bar',
template_path: 'some/path.hbl',
title: 'myFoo',
description: 'myFoo',
vars: [],
},
],
})
).toEqual([
{
type: 'foo',
dataset: 'nginx.foo',
title: expect.any(String),
release: 'ga',
package: 'nginx',
path: 'nginx',
streams: [
{
input: 'string',
vars: expect.any(Array),
template_path: 'some/path.hbl',
title: 'myFoo',
description: 'myFoo',
enabled: true,
},
],
},
]);
});
it('should not add dataset if already present', () => {
const datasetVar = {
name: 'data_stream.dataset',
type: 'text' as RegistryVarType,
title: 'local dataset',
description: 'some desc',
multi: false,
required: true,
show_user: true,
};
const result = getNormalizedDataStreams({
...integrationPkg,
type: 'input',
policy_templates: [
{
input: 'string',
type: 'foo',
name: 'bar',
template_path: 'some/path.hbl',
title: 'myFoo',
description: 'myFoo',
vars: [datasetVar],
},
],
});
expect(result).toHaveLength(1);
expect(result[0].streams).toHaveLength(1);
expect(result?.[0].streams?.[0]?.vars).toEqual([datasetVar]);
});
});
Loading