diff --git a/x-pack/plugins/fleet/server/services/package_policy.test.ts b/x-pack/plugins/fleet/server/services/package_policy.test.ts index ac88204f082b7..78a4d3d1a778d 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.test.ts @@ -2713,6 +2713,107 @@ describe('Package policy service', () => { expect(result.inputs[0]?.vars?.path.value).toEqual(['/var/log/logfile.log']); }); }); + + describe('when policy_template is defined on update, but undefined on existing input with matching type', () => { + it('generates the proper inputs, and adds a policy_template field', () => { + const basePackagePolicy: NewPackagePolicy = { + name: 'base-package-policy', + description: 'Base Package Policy', + namespace: 'default', + enabled: true, + policy_id: 'xxxx', + output_id: 'xxxx', + package: { + name: 'test-package', + title: 'Test Package', + version: '0.0.1', + }, + inputs: [ + { + type: 'logs', + enabled: true, + vars: { + path: { + type: 'text', + value: ['/var/log/logfile.log'], + }, + }, + streams: [], + }, + ], + }; + + const packageInfo: PackageInfo = { + name: 'test-package', + description: 'Test Package', + title: 'Test Package', + version: '0.0.1', + latestVersion: '0.0.1', + release: 'experimental', + format_version: '1.0.0', + owner: { github: 'elastic/fleet' }, + policy_templates: [ + { + name: 'template_1', + title: 'Template 1', + description: 'Template 1', + inputs: [ + { + type: 'logs', + title: 'Log', + description: 'Log Input', + vars: [ + { + name: 'path', + type: 'text', + }, + { + name: 'path_2', + type: 'text', + }, + ], + }, + ], + }, + ], + // @ts-ignore + assets: {}, + }; + + const inputsOverride: NewPackagePolicyInput[] = [ + { + type: 'logs', + enabled: true, + streams: [], + policy_template: 'template_1', + vars: { + path: { + type: 'text', + value: '/var/log/new-logfile.log', + }, + path_2: { + type: 'text', + value: '/var/log/custom.log', + }, + }, + }, + ]; + + const result = updatePackageInputs( + basePackagePolicy, + packageInfo, + // TODO: Update this type assertion when the `InputsOverride` type is updated such + // that it no longer causes unresolvable type errors when used directly + inputsOverride as InputsOverride[], + false + ); + + expect(result.inputs.length).toBe(1); + expect(result.inputs[0]?.vars?.path.value).toEqual(['/var/log/logfile.log']); + expect(result.inputs[0]?.vars?.path_2.value).toBe('/var/log/custom.log'); + expect(result.inputs[0]?.policy_template).toBe('template_1'); + }); + }); }); }); diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 5ac348ad7c8a2..cef27d79a184a 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -1066,11 +1066,26 @@ export function updatePackageInputs( ]; for (const update of inputsUpdated) { - // If update have an undefined policy template - // we only match on `type` . - let originalInput = update.policy_template - ? inputs.find((i) => i.type === update.type && i.policy_template === update.policy_template) - : inputs.find((i) => i.type === update.type); + let originalInput: NewPackagePolicyInput | undefined; + + if (update.policy_template) { + // If the updated value defines a policy template, try to find an original input + // with the same policy template value + const matchingInput = inputs.find( + (i) => i.type === update.type && i.policy_template === update.policy_template + ); + + // If we didn't find an input with the same policy template, try to look for one + // with the same type, but with an undefined policy template. This ensures we catch + // cases where we're upgrading an older policy from before policy template was + // reliably define on package policy inputs. + originalInput = + matchingInput || inputs.find((i) => i.type === update.type && !i.policy_template); + } else { + // For inputs that don't specify a policy template, just grab the first input + // that matches its `type` + originalInput = inputs.find((i) => i.type === update.type); + } // If there's no corresponding input on the original package policy, just // take the override value from the new package as-is. This case typically @@ -1091,6 +1106,12 @@ export function updatePackageInputs( originalInput.keep_enabled = update.keep_enabled; } + // `policy_template` should always be defined, so if we have an older policy here we need + // to ensure we set it + if (originalInput.policy_template === undefined && update.policy_template !== undefined) { + originalInput.policy_template = update.policy_template; + } + if (update.vars) { const indexOfInput = inputs.indexOf(originalInput); inputs[indexOfInput] = deepMergeVars(originalInput, update, true) as NewPackagePolicyInput;