Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -428,6 +428,100 @@ input: logs
});
});

const rerouteConfigVars = {
reroute_config: {
type: 'yaml',
value: `
- if:
and:
- not.has_fields: _conf.dataset
- regexp.message: "devid=\\"?FG"
then:
- add_fields:
target: ''
fields:
_conf.dataset: "fortinet_fortigate.log"
- if:
and:
- not.has_fields: _conf.dataset
- regexp.message: " CheckPoint [0-9]+ - "
then:
- add_fields:
target: ''
fields:
_conf.dataset: "checkpoint.firewall"
_conf.tz_offset: "UTC"
`,
},
};

it('should handle deeply nested yaml values without producing compact mappings', () => {
const streamTemplate = `
input: udp
host: "0.0.0.0:9515"
reroute_config: {{reroute_config}}
`;

const output = compileTemplate(rerouteConfigVars, getMockedMetaVariable(), streamTemplate);
expect(output).toEqual({
input: 'udp',
host: '0.0.0.0:9515',
reroute_config: [
{
if: {
and: [{ 'not.has_fields': '_conf.dataset' }, { 'regexp.message': 'devid="?FG' }],
},
then: [
{
add_fields: {
target: '',
fields: { '_conf.dataset': 'fortinet_fortigate.log' },
},
},
],
},
{
if: {
and: [
{ 'not.has_fields': '_conf.dataset' },
{ 'regexp.message': ' CheckPoint [0-9]+ - ' },
],
},
then: [
{
add_fields: {
target: '',
fields: {
'_conf.dataset': 'checkpoint.firewall',
'_conf.tz_offset': 'UTC',
},
},
},
],
},
],
});
});

it('should handle root-level yaml variables with values containing double quotes (syslog_router pattern)', () => {
const streamTemplate = `
input: udp
host: "0.0.0.0:9515"
processors:
- add_locale: ~
{{#if reroute_config}}
{{reroute_config}}
{{/if}}
`;

const output = compileTemplate(rerouteConfigVars, getMockedMetaVariable(), streamTemplate);
expect(output.processors).toBeDefined();
expect(output.processors).toHaveLength(3);
expect(output.processors[0]).toEqual({ add_locale: null });
expect(output.processors[1].if.and[1]['regexp.message']).toBe('devid="?FG');
expect(output.processors[2].if.and[1]['regexp.message']).toBe(' CheckPoint [0-9]+ - ');
});

it('should support $$$$ yaml values at root level', () => {
const streamTemplate = `
input: logs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,17 @@ export function compileTemplate(
throw new PackageInvalidArchiveError(`Error while compiling agent template: ${err.message}`);
}

compiledTemplate = replaceRootLevelYamlVariables(yamlValues, compiledTemplate);

// Normalize multi-line double-quoted YAML scalars. The yaml package (unlike
// js-yaml) rejects literal newlines inside double-quoted strings. Values that
// were JSON-stringified and then had parameters resolved may contain actual
// newlines (doubled by handleMultilineStringFormatter). Apply YAML double-quoted
// folding semantics: N consecutive newlines become N-1 \n escape sequences,
// matching the output that js-yaml.load produced from the multi-line format.
// Must run before replaceRootLevelYamlVariables: stringify output may contain
// unquoted `"` chars (e.g. regexp patterns) that cause this regex to match
// across lines and corrupt the YAML structure.
compiledTemplate = compiledTemplate.replace(/"(?:[^"\\]|\\.)*"/gs, (match) =>
match.includes('\n')
? match.replace(/\n+/g, (newlines) => '\\n'.repeat(newlines.length - 1))
: match
);

compiledTemplate = replaceRootLevelYamlVariables(yamlValues, compiledTemplate);

try {
const yamlFromCompiledTemplate = parse(compiledTemplate);

Expand Down Expand Up @@ -342,7 +339,7 @@ function replaceRootLevelYamlVariables(yamlVariables: { [k: string]: any }, yaml
let patchedTemplate = yamlTemplate;
Object.entries(yamlVariables).forEach(([key, val]) => {
patchedTemplate = patchedTemplate.replace(new RegExp(`^"${key}"`, 'gm'), () =>
val ? stringify(val) : ''
val ? stringify(val, { collectionStyle: 'block', lineWidth: 0 }) : ''
);
});

Expand Down
Loading