[Test Serverless] Move telemetry tests to common (#184855)

This commit is contained in:
Alejandro Fernández Haro 2024-06-11 13:15:33 +02:00 committed by GitHub
parent b757eac4f8
commit 3c1cc8bf4a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 95 additions and 265 deletions

View file

@ -5,57 +5,60 @@
* 2.0.
*/
import { UsageStatsPayload } from '@kbn/telemetry-collection-manager-plugin/server';
import type { UsageStatsPayload } from '@kbn/telemetry-collection-manager-plugin/server';
import {
ELASTIC_HTTP_VERSION_HEADER,
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
} from '@kbn/core-http-common';
import { FtrProviderContext } from '../ftr_provider_context';
import type { FtrProviderContext } from '../ftr_provider_context';
export interface UsageStatsPayloadTestFriendly extends UsageStatsPayload {
// Overwriting the `object` type to a more test-friendly type
stack_stats: Record<string, any>;
}
export interface GetTelemetryStatsOpts {
authHeader: Record<string, string>;
}
export function UsageAPIProvider({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
async function getTelemetryStats(
payload: {
unencrypted: true;
refreshCache?: boolean;
},
options?: { authHeader: Record<string, string> }
opts?: GetTelemetryStatsOpts
): Promise<Array<{ clusterUuid: string; stats: UsageStatsPayloadTestFriendly }>>;
async function getTelemetryStats(
payload: {
unencrypted: false;
refreshCache?: boolean;
},
options?: { authHeader: Record<string, string> }
): Promise<Array<{ clusterUuid: string; stats: string }>>;
async function getTelemetryStats(
payload: {
unencrypted: false;
refreshCache?: boolean;
},
options?: { authHeader: Record<string, string> }
opts?: GetTelemetryStatsOpts
): Promise<Array<{ clusterUuid: string; stats: string }>>;
async function getTelemetryStats(
payload: {
unencrypted?: boolean;
refreshCache?: boolean;
},
options?: { authHeader: Record<string, string> }
opts?: GetTelemetryStatsOpts
): Promise<Array<{ clusterUuid: string; stats: UsageStatsPayloadTestFriendly | string }>> {
const { body } = await supertest
const client = opts?.authHeader ? supertestWithoutAuth : supertest;
const request = client
.post('/internal/telemetry/clusters/_stats')
.set('kbn-xsrf', 'xxx')
.set(options?.authHeader ?? {})
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send({ refreshCache: true, ...payload })
.expect(200);
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
if (opts?.authHeader) {
request.set(opts.authHeader);
}
const { body } = await request.send({ refreshCache: true, ...payload }).expect(200);
return body;
}

View file

@ -0,0 +1,17 @@
/*
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('telemetry', function () {
this.tags(['esGate']);
loadTestFile(require.resolve('./snapshot_telemetry'));
loadTestFile(require.resolve('./telemetry_config'));
});
}

View file

@ -18,6 +18,8 @@ import type { UsageStatsPayloadTestFriendly } from '../../../../../test/api_inte
export default function ({ getService }: FtrProviderContext) {
const usageApi = getService('usageAPI');
const svlCommonApi = getService('svlCommonApi');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const svlUserManager = getService('svlUserManager');
describe('Snapshot telemetry', function () {
@ -32,6 +34,7 @@ export default function ({ getService }: FtrProviderContext) {
);
stats = unencryptedPayload.stats;
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
@ -48,15 +51,20 @@ export default function ({ getService }: FtrProviderContext) {
}
});
it('includes the serverless info in the body', async () => {
const [unencryptedPayload] = await usageApi.getTelemetryStats(
{ unencrypted: true },
{ authHeader: roleAuthc.apiKeyHeader }
it('includes the project type info in the body', async () => {
expect(stats.stack_stats.kibana?.plugins?.telemetry?.labels?.serverless).toMatch(
/security|observability|search/
);
expect(
unencryptedPayload.stats.stack_stats.kibana?.plugins?.telemetry?.labels?.serverless
).toBe('observability');
const { body } = await supertestWithoutAuth
.get('/api/telemetry/v2/config')
.set(svlCommonApi.getCommonRequestHeader())
.set(roleAuthc.apiKeyHeader)
.expect(200);
expect(stats.stack_stats.kibana?.plugins?.telemetry?.labels?.serverless).toBe(
body.labels.serverless
);
});
});
}

View file

@ -6,7 +6,7 @@
*/
import { expect } from 'expect';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default function telemetryConfigTest({ getService }: FtrProviderContext) {
@ -15,58 +15,59 @@ export default function telemetryConfigTest({ getService }: FtrProviderContext)
const supertestWithoutAuth = getService('supertestWithoutAuth');
describe('/api/telemetry/v2/config API Telemetry config', function () {
const baseConfig = {
allowChangingOptInStatus: false,
optIn: true,
sendUsageFrom: 'server',
telemetryNotifyUserAboutOptInDefault: false,
labels: {
serverless: 'observability',
},
};
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
const baseConfig = {
allowChangingOptInStatus: false,
optIn: true,
sendUsageFrom: 'server',
telemetryNotifyUserAboutOptInDefault: false,
};
it('GET should get the default config', async () => {
const { body } = await supertestWithoutAuth
.get('/api/telemetry/v2/config')
.set(internalReqHeader)
.set(svlCommonApi.getCommonRequestHeader())
.set(roleAuthc.apiKeyHeader)
.expect(200);
expect(body).toMatchObject(baseConfig);
});
it.skip('GET should get updated labels after dynamically updating them', async () => {
it('GET should get updated labels after dynamically updating them', async () => {
const { body: initialConfig } = await supertestWithoutAuth
.get('/api/telemetry/v2/config')
.set(svlCommonApi.getCommonRequestHeader())
.set(roleAuthc.apiKeyHeader)
.expect(200);
await supertestWithoutAuth
.put('/internal/core/_settings')
.set(internalReqHeader)
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.set('elastic-api-version', '1')
.send({ 'telemetry.labels.journeyName': 'my-ftr-test' })
.expect(200, { ok: true });
const response = await supertestWithoutAuth
await supertestWithoutAuth
.get('/api/telemetry/v2/config')
.set(internalReqHeader)
.set(roleAuthc.apiKeyHeader);
expect(response.status).toBe(200);
expect(response.body).toEqual({
...baseConfig,
labels: expect.objectContaining({
...baseConfig.labels,
journeyName: 'my-ftr-test',
}),
});
.set(svlCommonApi.getCommonRequestHeader())
.set(roleAuthc.apiKeyHeader)
.expect(200, {
...initialConfig,
labels: {
...initialConfig.labels,
journeyName: 'my-ftr-test',
},
});
});
});
}

View file

@ -30,6 +30,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
require.resolve('../../common/grok_debugger'),
require.resolve('../../common/painless_lab'),
require.resolve('../../common/console'),
require.resolve('../../common/telemetry'),
],
junit: {
reportName: 'Serverless Observability API Integration Tests - Common Group 1',

View file

@ -21,6 +21,10 @@ export default createTestConfig({
// include settings from project controller
// https://github.com/elastic/project-controller/blob/main/internal/project/observability/config/elasticsearch.yml
esServerArgs: ['xpack.ml.dfa.enabled=false'],
// defined in MKI control plane
kbnServerArgs: ['--xpack.uptime.service.manifestUrl=mockDevUrl'],
kbnServerArgs: [
// defined in MKI control plane
'--xpack.uptime.service.manifestUrl=mockDevUrl',
// useful for testing (also enabled in MKI QA)
'--coreApp.allowDynamicConfigOverrides=true',
],
});

View file

@ -11,8 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
describe('Serverless observability API', function () {
this.tags(['esGate']);
loadTestFile(require.resolve('./telemetry/snapshot_telemetry'));
loadTestFile(require.resolve('./telemetry/telemetry_config'));
loadTestFile(require.resolve('./apm_api_integration/feature_flags.ts'));
loadTestFile(require.resolve('./cases'));
loadTestFile(require.resolve('./burn_rate_rule/burn_rate_rule'));

View file

@ -28,6 +28,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
require.resolve('../../common/core'),
require.resolve('../../common/reporting'),
require.resolve('../../common/console'),
require.resolve('../../common/telemetry'),
],
junit: {
reportName: 'Serverless Search API Integration Tests - Common Group 1',

View file

@ -18,4 +18,8 @@ export default createTestConfig({
// include settings from project controller
// https://github.com/elastic/project-controller/blob/main/internal/project/esproject/config/elasticsearch.yml
esServerArgs: [],
kbnServerArgs: [
// useful for testing (also enabled in MKI QA)
'--coreApp.allowDynamicConfigOverrides=true',
],
});

View file

@ -11,8 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
describe('Serverless search API', function () {
this.tags(['esGate']);
loadTestFile(require.resolve('./telemetry/snapshot_telemetry'));
loadTestFile(require.resolve('./telemetry/telemetry_config'));
loadTestFile(require.resolve('./cases/find_cases'));
loadTestFile(require.resolve('./cases/post_case'));
loadTestFile(require.resolve('./serverless_search'));

View file

@ -1,45 +0,0 @@
/*
* 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 expect from 'expect';
import deepmerge from 'deepmerge';
import { assertTelemetryPayload } from '@kbn/telemetry-tools';
import ossRootTelemetrySchema from '@kbn/telemetry-plugin/schema/oss_root.json';
import ossPluginsTelemetrySchema from '@kbn/telemetry-plugin/schema/oss_plugins.json';
import xpackRootTelemetrySchema from '@kbn/telemetry-collection-xpack-plugin/schema/xpack_root.json';
import xpackPluginsTelemetrySchema from '@kbn/telemetry-collection-xpack-plugin/schema/xpack_plugins.json';
import type { FtrProviderContext } from '../../../ftr_provider_context';
import type { UsageStatsPayloadTestFriendly } from '../../../../../test/api_integration/services/usage_api';
export default function ({ getService }: FtrProviderContext) {
const usageApi = getService('usageAPI');
describe('Snapshot telemetry', function () {
let stats: UsageStatsPayloadTestFriendly;
before(async () => {
const [unencryptedPayload] = await usageApi.getTelemetryStats({ unencrypted: true });
stats = unencryptedPayload.stats;
});
it('should pass the schema validation (ensures BWC with Classic offering)', () => {
const root = deepmerge(ossRootTelemetrySchema, xpackRootTelemetrySchema);
const plugins = deepmerge(ossPluginsTelemetrySchema, xpackPluginsTelemetrySchema);
try {
assertTelemetryPayload({ root, plugins }, stats);
} catch (err) {
err.message = `The telemetry schemas in are out-of-date. Please define the schema of your collector and run "node scripts/telemetry_check --fix" to update them: ${err.message}`;
throw err;
}
});
it('includes the serverless info in the body', async () => {
expect(stats.stack_stats.kibana?.plugins?.telemetry?.labels?.serverless).toBe('search');
});
});
}

View file

@ -1,58 +0,0 @@
/*
* 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 { expect } from 'expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default function telemetryConfigTest({ getService }: FtrProviderContext) {
const svlCommonApi = getService('svlCommonApi');
const supertest = getService('supertest');
describe('/api/telemetry/v2/config API Telemetry config', () => {
const baseConfig = {
allowChangingOptInStatus: false,
optIn: true,
sendUsageFrom: 'server',
telemetryNotifyUserAboutOptInDefault: false,
labels: {
serverless: 'search',
},
};
it('GET should get the default config', async () => {
const { body } = await supertest
.get('/api/telemetry/v2/config')
.set(svlCommonApi.getCommonRequestHeader())
.expect(200);
expect(body).toMatchObject(baseConfig);
});
// coreApp.allowDynamicConfigOverrides is disabled
it.skip('GET should get updated labels after dynamically updating them', async () => {
const uniqueJourneyName = `my-ftr-test-${new Date().getMilliseconds()}`;
await supertest
.put('/internal/core/_settings')
.set(svlCommonApi.getInternalRequestHeader())
.set('elastic-api-version', '1')
.send({ 'telemetry.labels.journeyName': uniqueJourneyName })
.expect(200, { ok: true });
const { body } = await supertest
.get('/api/telemetry/v2/config')
.set(svlCommonApi.getCommonRequestHeader())
.expect(200);
expect(body).toMatchObject({
...baseConfig,
labels: {
...baseConfig.labels,
journeyName: uniqueJourneyName,
},
});
});
});
}

View file

@ -30,6 +30,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
require.resolve('../../common/grok_debugger'),
require.resolve('../../common/painless_lab'),
require.resolve('../../common/console'),
require.resolve('../../common/telemetry'),
],
junit: {
reportName: 'Serverless Security API Integration Tests - Common Group 1',

View file

@ -21,5 +21,7 @@ export default createTestConfig({
kbnServerArgs: [
// disable fleet task that writes to metrics.fleet_server.* data streams, impacting functional tests
`--xpack.task_manager.unsafe.exclude_task_types=${JSON.stringify(['Fleet-Metrics-Task'])}`,
// useful for testing (also enabled in MKI QA)
'--coreApp.allowDynamicConfigOverrides=true',
],
});

View file

@ -11,8 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
describe('Serverless security API', function () {
this.tags(['esGate']);
loadTestFile(require.resolve('./telemetry/snapshot_telemetry'));
loadTestFile(require.resolve('./telemetry/telemetry_config'));
loadTestFile(require.resolve('./cases'));
loadTestFile(require.resolve('./cloud_security_posture'));
});

View file

@ -1,45 +0,0 @@
/*
* 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 expect from 'expect';
import deepmerge from 'deepmerge';
import ossRootTelemetrySchema from '@kbn/telemetry-plugin/schema/oss_root.json';
import xpackRootTelemetrySchema from '@kbn/telemetry-collection-xpack-plugin/schema/xpack_root.json';
import ossPluginsTelemetrySchema from '@kbn/telemetry-plugin/schema/oss_plugins.json';
import xpackPluginsTelemetrySchema from '@kbn/telemetry-collection-xpack-plugin/schema/xpack_plugins.json';
import { assertTelemetryPayload } from '@kbn/telemetry-tools';
import { FtrProviderContext } from '../../../ftr_provider_context';
import type { UsageStatsPayloadTestFriendly } from '../../../../../test/api_integration/services/usage_api';
export default function ({ getService }: FtrProviderContext) {
const usageApi = getService('usageAPI');
describe('Snapshot telemetry', function () {
let stats: UsageStatsPayloadTestFriendly;
before(async () => {
const [unencryptedPayload] = await usageApi.getTelemetryStats({ unencrypted: true });
stats = unencryptedPayload.stats;
});
it('should pass the schema validation (ensures BWC with Classic offering)', () => {
const root = deepmerge(ossRootTelemetrySchema, xpackRootTelemetrySchema);
const plugins = deepmerge(ossPluginsTelemetrySchema, xpackPluginsTelemetrySchema);
try {
assertTelemetryPayload({ root, plugins }, stats);
} catch (err) {
err.message = `The telemetry schemas in are out-of-date. Please define the schema of your collector and run "node scripts/telemetry_check --fix" to update them: ${err.message}`;
throw err;
}
});
it('includes the serverless info in the body', async () => {
expect(stats.stack_stats.kibana?.plugins?.telemetry?.labels?.serverless).toBe('security');
});
});
}

View file

@ -1,58 +0,0 @@
/*
* 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 { expect } from 'expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default function telemetryConfigTest({ getService }: FtrProviderContext) {
const svlCommonApi = getService('svlCommonApi');
const supertest = getService('supertest');
// failsOnMKI, see https://github.com/elastic/kibana/issues/180348
describe('/api/telemetry/v2/config API Telemetry config', function () {
this.tags(['failsOnMKI']);
const baseConfig = {
allowChangingOptInStatus: false,
optIn: true,
sendUsageFrom: 'server',
telemetryNotifyUserAboutOptInDefault: false,
labels: {
serverless: 'security',
},
};
it('GET should get the default config', async () => {
const { body } = await supertest
.get('/api/telemetry/v2/config')
.set(svlCommonApi.getCommonRequestHeader())
.expect(200);
expect(body).toMatchObject(baseConfig);
});
// coreApp.allowDynamicConfigOverrides is disabled
it.skip('GET should get updated labels after dynamically updating them', async () => {
await supertest
.put('/internal/core/_settings')
.set(svlCommonApi.getInternalRequestHeader())
.set('elastic-api-version', '1')
.send({ 'telemetry.labels.journeyName': 'my-ftr-test' })
.expect(200, { ok: true });
await supertest
.get('/api/telemetry/v2/config')
.set(svlCommonApi.getCommonRequestHeader())
.expect(200, {
...baseConfig,
labels: {
...baseConfig.labels,
journeyName: 'my-ftr-test',
},
});
});
});
}