Skip to content

Commit 3149dd9

Browse files
authored
[Fleet] Ensure custom data stream types and data sets are included in policies (#236016)
Customization of data stream type and dataset relies on having the `data_stream` object in the compiled stream. In the case of OTel inputs the compiled stream doesn't contain this object, as it is not supported by the OTel collector. Get these values directly from the user-defined variables.
1 parent 1e6783e commit 3149dd9

File tree

5 files changed

+145
-2
lines changed

5 files changed

+145
-2
lines changed

x-pack/platform/plugins/shared/fleet/cypress/e2e/input_packages_real.cy.ts

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { login } from '../tasks/login';
2020
import { request } from '../tasks/common';
2121

2222
const INPUT_TEST_PACKAGE = 'input_package-1.0.0';
23+
const OTEL_INPUT_TEST_PACKAGE = 'otel_input_package-1.0.0';
2324

2425
describe('Input package with custom data stream type', () => {
2526
beforeEach(() => {
@@ -121,3 +122,127 @@ describe('Input package with custom data stream type', () => {
121122
cy.get('[data-test-subj="templateDetails"').contains(`${dataStreamType}-${datasetName}-*`);
122123
});
123124
});
125+
126+
describe('OTel input package with custom data stream type', () => {
127+
beforeEach(() => {
128+
login();
129+
});
130+
131+
const agentPolicyId = 'test-otel-input-package-policy';
132+
const agentPolicyName = 'Test input package policy';
133+
const packagePolicyName = 'input-package-policy';
134+
const datasetName = 'check'; // Default from the package.
135+
const dataStreamType = 'logs';
136+
137+
before(() => {
138+
cy.task('installTestPackage', OTEL_INPUT_TEST_PACKAGE);
139+
140+
request({
141+
method: 'POST',
142+
url: `/api/fleet/agent_policies`,
143+
body: {
144+
id: agentPolicyId,
145+
name: agentPolicyName,
146+
description: 'desc',
147+
namespace: 'default',
148+
monitoring_enabled: [],
149+
},
150+
headers: { 'kbn-xsrf': 'cypress', 'Elastic-Api-Version': `${API_VERSIONS.public.v1}` },
151+
});
152+
});
153+
154+
after(() => {
155+
cleanupAgentPolicies();
156+
cy.task('uninstallTestPackage', OTEL_INPUT_TEST_PACKAGE);
157+
});
158+
159+
it('should successfully create a package policy', () => {
160+
cy.visit(`/app/integrations/detail/${OTEL_INPUT_TEST_PACKAGE}/overview`);
161+
cy.getBySel(ADD_INTEGRATION_POLICY_BTN).click();
162+
163+
cy.getBySel(POLICY_EDITOR.POLICY_NAME_INPUT).click().clear().type(packagePolicyName);
164+
cy.getBySel('multiTextInput-http-endpoints-to-check')
165+
.find('[data-test-subj="multiTextInputRow-0"]')
166+
.click()
167+
.type('https://www.elastic.co/integrations');
168+
169+
// Select logs data stream type.
170+
cy.get('[data-test-subj^="advancedStreamOptionsToggle"]').click();
171+
cy.get('[data-test-subj="packagePolicyDataStreamType"')
172+
.find(`label[for="${dataStreamType}"]`)
173+
.click();
174+
175+
cy.getBySel(EXISTING_HOSTS_TAB).click();
176+
177+
cy.getBySel(POLICY_EDITOR.AGENT_POLICY_SELECT).click();
178+
cy.getBySel('agentPolicyMultiItem').each(($el) => {
179+
if ($el.text() === agentPolicyName) {
180+
$el.trigger('click');
181+
}
182+
});
183+
cy.wait(1000); // wait for policy id to be set
184+
cy.getBySel(CREATE_PACKAGE_POLICY_SAVE_BTN).click();
185+
186+
cy.getBySel(CONFIRM_MODAL.CANCEL_BUTTON).click();
187+
});
188+
189+
it(`agent policy configures the dataset and type`, () => {
190+
cy.request({
191+
method: 'GET',
192+
url: `/api/fleet/agent_policies/${agentPolicyId}/full`,
193+
}).then(({ body }) => {
194+
expect(body.item).to.have.property('processors');
195+
let routingTransform;
196+
Object.entries(body.item.processors).forEach(([name, config]) => {
197+
if (!name.match(/transform\/.*-routing/)) {
198+
return;
199+
}
200+
routingTransform = config;
201+
});
202+
expect(routingTransform).to.deep.equal({
203+
log_statements: [
204+
{
205+
context: 'log',
206+
statements: [
207+
`set(attributes["data_stream.type"], "${dataStreamType}")`,
208+
`set(attributes["data_stream.dataset"], "${datasetName}")`,
209+
'set(attributes["data_stream.namespace"], "default")',
210+
],
211+
},
212+
],
213+
});
214+
});
215+
});
216+
217+
it(`${dataStreamType} checkbox should be checked`, () => {
218+
cy.visit(`/app/integrations/detail/${OTEL_INPUT_TEST_PACKAGE}/policies`);
219+
220+
cy.getBySel(INTEGRATION_NAME_LINK).contains(packagePolicyName).click();
221+
222+
cy.get('button').contains('Change defaults').click();
223+
cy.get('[data-test-subj^="advancedStreamOptionsToggle"]').click();
224+
cy.get('[data-test-subj="packagePolicyDataStreamType"')
225+
.find(`input#${dataStreamType}`)
226+
.should('be.checked');
227+
});
228+
229+
it('should not allow to edit data stream type', () => {
230+
cy.visit(`/app/integrations/detail/${OTEL_INPUT_TEST_PACKAGE}/policies`);
231+
232+
cy.getBySel(INTEGRATION_NAME_LINK).contains(packagePolicyName).click();
233+
234+
cy.get('button').contains('Change defaults').click();
235+
cy.get('[data-test-subj^="advancedStreamOptionsToggle"]').click();
236+
cy.get('[data-test-subj="packagePolicyDataStreamType"')
237+
.find('input')
238+
.should('have.length', 3)
239+
.each(($el) => cy.wrap($el).should('be.disabled'));
240+
});
241+
242+
it('has an index template', () => {
243+
cy.visit(`app/management/data/index_management/templates/${dataStreamType}-${datasetName}`);
244+
245+
// Check that the index pattern appears in the view.
246+
cy.get('[data-test-subj="templateDetails"').contains(`${dataStreamType}-${datasetName}.otel-*`);
247+
});
248+
});
31.9 KB
Binary file not shown.

x-pack/platform/plugins/shared/fleet/server/services/agent_policies/otel_collector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ function generateOTelAttributesTransform(
9393
context = 'span';
9494
break;
9595
default:
96-
throw new Error(`unexpected data stream type ${type}`);
96+
throw new FleetError(`unexpected data stream type ${type}`);
9797
}
9898
return {
9999
[`transform/${suffix}-routing`]: {

x-pack/platform/plugins/shared/fleet/server/services/agent_policies/package_policies_to_agent_inputs.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ import type {
2020
} from '../../types';
2121
import { DEFAULT_OUTPUT } from '../../constants';
2222
import { pkgToPkgKey } from '../epm/registry';
23-
import { GLOBAL_DATA_TAG_EXCLUDED_INPUTS } from '../../../common/constants/epm';
23+
import {
24+
DATASET_VAR_NAME,
25+
DATA_STREAM_TYPE_VAR_NAME,
26+
GLOBAL_DATA_TAG_EXCLUDED_INPUTS,
27+
OTEL_COLLECTOR_INPUT_TYPE,
28+
} from '../../../common/constants/epm';
2429

2530
const isPolicyEnabled = (packagePolicy: PackagePolicy) => {
2631
return packagePolicy.enabled && packagePolicy.inputs && packagePolicy.inputs.length;
@@ -145,6 +150,18 @@ export const getFullInputStreams = (
145150
return acc;
146151
}, {} as { [k: string]: any }),
147152
};
153+
if (input.type === OTEL_COLLECTOR_INPUT_TYPE) {
154+
// otelcol inputs are not going to have the data_stream type and dataset in
155+
// the compiled stream, get them directly from the user-defined variables.
156+
const dsTypeVar = stream.vars?.[DATA_STREAM_TYPE_VAR_NAME]?.value;
157+
const datasetVar = stream.vars?.[DATASET_VAR_NAME]?.value;
158+
fullStream.data_stream = {
159+
...fullStream.data_stream,
160+
...(dsTypeVar ? { type: dsTypeVar } : {}),
161+
...(datasetVar ? { dataset: datasetVar } : {}),
162+
};
163+
}
164+
148165
streamsOriginalIdsMap?.set(fullStream.id, streamId);
149166

150167
return fullStream;

x-pack/platform/test/fleet_cypress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
4343
// add feature flags here
4444
`--xpack.fleet.enableExperimental=${JSON.stringify([
4545
'agentTamperProtectionEnabled',
46+
'enableOtelIntegrations',
4647
'subfeaturePrivileges',
4748
])}`,
4849

0 commit comments

Comments
 (0)