Skip to content

Commit 64017f0

Browse files
committed
[Ingest] Support root level yaml variables in agent stream template (#66120)
1 parent 29dcaaf commit 64017f0

2 files changed

Lines changed: 64 additions & 38 deletions

File tree

x-pack/plugins/ingest_manager/server/services/epm/agent/agent.test.ts

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ import { createStream } from './agent';
99
describe('createStream', () => {
1010
it('should work', () => {
1111
const streamTemplate = `
12-
input: log
13-
paths:
14-
{{#each paths}}
15-
- {{this}}
16-
{{/each}}
17-
exclude_files: [".gz$"]
18-
processors:
19-
- add_locale: ~
20-
password: {{password}}
21-
{{#if password}}
22-
hidden_password: {{password}}
23-
{{/if}}
12+
input: log
13+
paths:
14+
{{#each paths}}
15+
- {{this}}
16+
{{/each}}
17+
exclude_files: [".gz$"]
18+
processors:
19+
- add_locale: ~
20+
password: {{password}}
21+
{{#if password}}
22+
hidden_password: {{password}}
23+
{{/if}}
2424
`;
2525
const vars = {
2626
paths: { value: ['/usr/local/var/log/nginx/access.log'] },
@@ -39,13 +39,16 @@ describe('createStream', () => {
3939

4040
it('should support yaml values', () => {
4141
const streamTemplate = `
42-
input: redis/metrics
43-
metricsets: ["key"]
44-
test: null
45-
password: {{password}}
46-
{{#if key.patterns}}
47-
key.patterns: {{key.patterns}}
48-
{{/if}}
42+
input: redis/metrics
43+
metricsets: ["key"]
44+
test: null
45+
password: {{password}}
46+
{{custom}}
47+
custom: {{ custom }}
48+
{{#if key.patterns}}
49+
key.patterns: {{key.patterns}}
50+
{{/if}}
51+
{{ testEmpty }}
4952
`;
5053
const vars = {
5154
'key.patterns': {
@@ -55,6 +58,12 @@ describe('createStream', () => {
5558
pattern: '*'
5659
`,
5760
},
61+
custom: {
62+
type: 'yaml',
63+
value: `
64+
foo: bar
65+
`,
66+
},
5867
password: { type: 'password', value: '' },
5968
};
6069

@@ -70,6 +79,8 @@ describe('createStream', () => {
7079
},
7180
],
7281
password: '',
82+
foo: 'bar',
83+
custom: { foo: 'bar' },
7384
});
7485
});
7586
});

x-pack/plugins/ingest_manager/server/services/epm/agent/agent.ts

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,32 @@
55
*/
66

77
import Handlebars from 'handlebars';
8-
import { safeLoad } from 'js-yaml';
8+
import { safeLoad, safeDump } from 'js-yaml';
99
import { DatasourceConfigRecord } from '../../../../common';
1010

11+
export function createStream(variables: DatasourceConfigRecord, streamTemplate: string) {
12+
const { vars, yamlValues } = buildTemplateVariables(variables, streamTemplate);
13+
14+
const template = Handlebars.compile(streamTemplate, { noEscape: true });
15+
let stream = template(vars);
16+
stream = replaceRootLevelYamlVariables(yamlValues, stream);
17+
18+
const yamlFromStream = safeLoad(stream, {});
19+
20+
// Hack to keep empty string ('') values around in the end yaml because
21+
// `safeLoad` replaces empty strings with null
22+
const patchedYamlFromStream = Object.entries(yamlFromStream).reduce((acc, [key, value]) => {
23+
if (value === null && typeof vars[key] === 'string' && vars[key].trim() === '') {
24+
acc[key] = '';
25+
} else {
26+
acc[key] = value;
27+
}
28+
return acc;
29+
}, {} as { [k: string]: any });
30+
31+
return replaceVariablesInYaml(yamlValues, patchedYamlFromStream);
32+
}
33+
1134
function isValidKey(key: string) {
1235
return key !== '__proto__' && key !== 'constructor' && key !== 'prototype';
1336
}
@@ -29,7 +52,7 @@ function replaceVariablesInYaml(yamlVariables: { [k: string]: any }, yaml: any)
2952
return yaml;
3053
}
3154

32-
function buildTemplateVariables(variables: DatasourceConfigRecord) {
55+
function buildTemplateVariables(variables: DatasourceConfigRecord, streamTemplate: string) {
3356
const yamlValues: { [k: string]: any } = {};
3457
const vars = Object.entries(variables).reduce((acc, [key, recordEntry]) => {
3558
// support variables with . like key.patterns
@@ -64,23 +87,15 @@ function buildTemplateVariables(variables: DatasourceConfigRecord) {
6487
return { vars, yamlValues };
6588
}
6689

67-
export function createStream(variables: DatasourceConfigRecord, streamTemplate: string) {
68-
const { vars, yamlValues } = buildTemplateVariables(variables);
69-
70-
const template = Handlebars.compile(streamTemplate, { noEscape: true });
71-
const stream = template(vars);
72-
const yamlFromStream = safeLoad(stream, {});
90+
function replaceRootLevelYamlVariables(yamlVariables: { [k: string]: any }, yamlTemplate: string) {
91+
if (Object.keys(yamlVariables).length === 0 || !yamlTemplate) {
92+
return yamlTemplate;
93+
}
7394

74-
// Hack to keep empty string ('') values around in the end yaml because
75-
// `safeLoad` replaces empty strings with null
76-
const patchedYamlFromStream = Object.entries(yamlFromStream).reduce((acc, [key, value]) => {
77-
if (value === null && typeof vars[key] === 'string' && vars[key].trim() === '') {
78-
acc[key] = '';
79-
} else {
80-
acc[key] = value;
81-
}
82-
return acc;
83-
}, {} as { [k: string]: any });
95+
let patchedTemplate = yamlTemplate;
96+
Object.entries(yamlVariables).forEach(([key, val]) => {
97+
patchedTemplate = patchedTemplate.replace(new RegExp(`^"${key}"`, 'gm'), safeDump(val));
98+
});
8499

85-
return replaceVariablesInYaml(yamlValues, patchedYamlFromStream);
100+
return patchedTemplate;
86101
}

0 commit comments

Comments
 (0)