Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Alejandro Fernández Haro <alejandro.haro@elastic.co>
This commit is contained in:
parent
3ac7fb9abf
commit
ed9c83ca07
8 changed files with 174 additions and 81 deletions
|
@ -22,6 +22,11 @@ describe('getKID', () => {
|
||||||
const kid = getKID(useProdKey);
|
const kid = getKID(useProdKey);
|
||||||
expect(kid).toBe('kibana1');
|
expect(kid).toBe('kibana1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`should fallback to development`, async () => {
|
||||||
|
const kid = getKID();
|
||||||
|
expect(kid).toBe('kibana_dev1');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('encryptTelemetry', () => {
|
describe('encryptTelemetry', () => {
|
||||||
|
@ -46,4 +51,10 @@ describe('encryptTelemetry', () => {
|
||||||
await encryptTelemetry(payload, { useProdKey: false });
|
await encryptTelemetry(payload, { useProdKey: false });
|
||||||
expect(mockEncrypt).toBeCalledWith('kibana_dev1', payload);
|
expect(mockEncrypt).toBeCalledWith('kibana_dev1', payload);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fallback to { useProdKey: false }', async () => {
|
||||||
|
const payload = { some: 'value' };
|
||||||
|
await encryptTelemetry(payload);
|
||||||
|
expect(mockEncrypt).toBeCalledWith('kibana_dev1', payload);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import { coreMock, httpServerMock } from '../../../core/server/mocks';
|
import { coreMock, httpServerMock } from '../../../core/server/mocks';
|
||||||
import { usageCollectionPluginMock } from '../../usage_collection/server/mocks';
|
import { usageCollectionPluginMock } from '../../usage_collection/server/mocks';
|
||||||
import { TelemetryCollectionManagerPlugin } from './plugin';
|
import { TelemetryCollectionManagerPlugin } from './plugin';
|
||||||
import { CollectionStrategyConfig, StatsGetterConfig } from './types';
|
import type { BasicStatsPayload, CollectionStrategyConfig, StatsGetterConfig } from './types';
|
||||||
import { TelemetrySavedObjectsClient } from './telemetry_saved_objects_client';
|
import { TelemetrySavedObjectsClient } from './telemetry_saved_objects_client';
|
||||||
|
|
||||||
function createCollectionStrategy(priority: number): jest.Mocked<CollectionStrategyConfig> {
|
function createCollectionStrategy(priority: number): jest.Mocked<CollectionStrategyConfig> {
|
||||||
|
@ -87,6 +87,15 @@ describe('Telemetry Collection Manager', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe(`after start`, () => {
|
describe(`after start`, () => {
|
||||||
|
const basicStats: BasicStatsPayload = {
|
||||||
|
cluster_uuid: 'clusterUuid',
|
||||||
|
cluster_name: 'clusterName',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
cluster_stats: {},
|
||||||
|
stack_stats: {},
|
||||||
|
version: 'version',
|
||||||
|
};
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
telemetryCollectionManager.start(coreMock.createStart());
|
telemetryCollectionManager.start(coreMock.createStart());
|
||||||
});
|
});
|
||||||
|
@ -97,19 +106,59 @@ describe('Telemetry Collection Manager', () => {
|
||||||
describe('unencrypted: false', () => {
|
describe('unencrypted: false', () => {
|
||||||
const config: StatsGetterConfig = { unencrypted: false };
|
const config: StatsGetterConfig = { unencrypted: false };
|
||||||
|
|
||||||
test('getStats returns empty because clusterDetails returns empty, and the soClient is an instance of the TelemetrySavedObjectsClient', async () => {
|
describe('getStats', () => {
|
||||||
collectionStrategy.clusterDetailsGetter.mockResolvedValue([]);
|
test('returns empty because clusterDetails returns empty, and the soClient is an instance of the TelemetrySavedObjectsClient', async () => {
|
||||||
await expect(setupApi.getStats(config)).resolves.toStrictEqual([]);
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([]);
|
||||||
expect(collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient).toBeInstanceOf(
|
await expect(setupApi.getStats(config)).resolves.toStrictEqual([]);
|
||||||
TelemetrySavedObjectsClient
|
expect(
|
||||||
);
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns encrypted payload', async () => {
|
||||||
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([
|
||||||
|
{ clusterUuid: 'clusterUuid' },
|
||||||
|
]);
|
||||||
|
collectionStrategy.statsGetter.mockResolvedValue([basicStats]);
|
||||||
|
await expect(setupApi.getStats(config)).resolves.toStrictEqual([expect.any(String)]);
|
||||||
|
expect(
|
||||||
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
test('getOptInStats returns empty', async () => {
|
|
||||||
collectionStrategy.clusterDetailsGetter.mockResolvedValue([]);
|
describe('getOptInStats', () => {
|
||||||
await expect(setupApi.getOptInStats(true, config)).resolves.toStrictEqual([]);
|
test('returns empty', async () => {
|
||||||
expect(collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient).toBeInstanceOf(
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([]);
|
||||||
TelemetrySavedObjectsClient
|
await expect(setupApi.getOptInStats(true, config)).resolves.toStrictEqual([]);
|
||||||
);
|
expect(
|
||||||
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns encrypted results for opt-in true', async () => {
|
||||||
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([
|
||||||
|
{ clusterUuid: 'clusterUuid' },
|
||||||
|
]);
|
||||||
|
await expect(setupApi.getOptInStats(true, config)).resolves.toStrictEqual([
|
||||||
|
expect.any(String),
|
||||||
|
]);
|
||||||
|
expect(
|
||||||
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns encrypted results for opt-in false', async () => {
|
||||||
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([
|
||||||
|
{ clusterUuid: 'clusterUuid' },
|
||||||
|
]);
|
||||||
|
await expect(setupApi.getOptInStats(false, config)).resolves.toStrictEqual([
|
||||||
|
expect.any(String),
|
||||||
|
]);
|
||||||
|
expect(
|
||||||
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('unencrypted: true', () => {
|
describe('unencrypted: true', () => {
|
||||||
|
@ -118,19 +167,60 @@ describe('Telemetry Collection Manager', () => {
|
||||||
request: httpServerMock.createKibanaRequest(),
|
request: httpServerMock.createKibanaRequest(),
|
||||||
};
|
};
|
||||||
|
|
||||||
test('getStats returns empty because clusterDetails returns empty, and the soClient is not an instance of the TelemetrySavedObjectsClient', async () => {
|
describe('getStats', () => {
|
||||||
collectionStrategy.clusterDetailsGetter.mockResolvedValue([]);
|
test('getStats returns empty because clusterDetails returns empty, and the soClient is not an instance of the TelemetrySavedObjectsClient', async () => {
|
||||||
await expect(setupApi.getStats(config)).resolves.toStrictEqual([]);
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([]);
|
||||||
expect(
|
await expect(setupApi.getStats(config)).resolves.toStrictEqual([]);
|
||||||
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
expect(
|
||||||
).not.toBeInstanceOf(TelemetrySavedObjectsClient);
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).not.toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
|
test('returns encrypted payload (assumes opted-in when no explicitly opted-out)', async () => {
|
||||||
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([
|
||||||
|
{ clusterUuid: 'clusterUuid' },
|
||||||
|
]);
|
||||||
|
collectionStrategy.statsGetter.mockResolvedValue([basicStats]);
|
||||||
|
await expect(setupApi.getStats(config)).resolves.toStrictEqual([
|
||||||
|
{ ...basicStats, collectionSource: 'test_collection' },
|
||||||
|
]);
|
||||||
|
expect(
|
||||||
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).not.toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
test('getOptInStats returns empty', async () => {
|
|
||||||
collectionStrategy.clusterDetailsGetter.mockResolvedValue([]);
|
describe('getOptInStats', () => {
|
||||||
await expect(setupApi.getOptInStats(true, config)).resolves.toStrictEqual([]);
|
test('returns empty', async () => {
|
||||||
expect(
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([]);
|
||||||
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
await expect(setupApi.getOptInStats(true, config)).resolves.toStrictEqual([]);
|
||||||
).not.toBeInstanceOf(TelemetrySavedObjectsClient);
|
expect(
|
||||||
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).not.toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns results for opt-in true', async () => {
|
||||||
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([
|
||||||
|
{ clusterUuid: 'clusterUuid' },
|
||||||
|
]);
|
||||||
|
await expect(setupApi.getOptInStats(true, config)).resolves.toStrictEqual([
|
||||||
|
{ cluster_uuid: 'clusterUuid', opt_in_status: true },
|
||||||
|
]);
|
||||||
|
expect(
|
||||||
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).not.toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns results for opt-in false', async () => {
|
||||||
|
collectionStrategy.clusterDetailsGetter.mockResolvedValue([
|
||||||
|
{ clusterUuid: 'clusterUuid' },
|
||||||
|
]);
|
||||||
|
await expect(setupApi.getOptInStats(false, config)).resolves.toStrictEqual([
|
||||||
|
{ cluster_uuid: 'clusterUuid', opt_in_status: false },
|
||||||
|
]);
|
||||||
|
expect(
|
||||||
|
collectionStrategy.clusterDetailsGetter.mock.calls[0][0].soClient
|
||||||
|
).not.toBeInstanceOf(TelemetrySavedObjectsClient);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,6 @@ import {
|
||||||
UsageStatsPayload,
|
UsageStatsPayload,
|
||||||
StatsCollectionContext,
|
StatsCollectionContext,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { isClusterOptedIn } from './util';
|
|
||||||
import { encryptTelemetry } from './encryption';
|
import { encryptTelemetry } from './encryption';
|
||||||
import { TelemetrySavedObjectsClient } from './telemetry_saved_objects_client';
|
import { TelemetrySavedObjectsClient } from './telemetry_saved_objects_client';
|
||||||
|
|
||||||
|
@ -233,7 +232,7 @@ export class TelemetryCollectionManagerPlugin
|
||||||
return usageData;
|
return usageData;
|
||||||
}
|
}
|
||||||
|
|
||||||
return encryptTelemetry(usageData.filter(isClusterOptedIn), {
|
return await encryptTelemetry(usageData, {
|
||||||
useProdKey: this.isDistributable,
|
useProdKey: this.isDistributable,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +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 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const isClusterOptedIn = (clusterUsage: any): boolean => {
|
|
||||||
return clusterUsage?.stack_stats?.kibana?.plugins?.telemetry?.opt_in_status === true;
|
|
||||||
};
|
|
|
@ -7,13 +7,27 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import expect from '@kbn/expect';
|
import expect from '@kbn/expect';
|
||||||
|
import supertestAsPromised from 'supertest-as-promised';
|
||||||
import { basicUiCounters } from './__fixtures__/ui_counters';
|
import { basicUiCounters } from './__fixtures__/ui_counters';
|
||||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
import type { FtrProviderContext } from '../../ftr_provider_context';
|
||||||
import { SavedObject } from '../../../../src/core/server';
|
import type { SavedObject } from '../../../../src/core/server';
|
||||||
import ossRootTelemetrySchema from '../../../../src/plugins/telemetry/schema/oss_root.json';
|
import ossRootTelemetrySchema from '../../../../src/plugins/telemetry/schema/oss_root.json';
|
||||||
import ossPluginsTelemetrySchema from '../../../../src/plugins/telemetry/schema/oss_plugins.json';
|
import ossPluginsTelemetrySchema from '../../../../src/plugins/telemetry/schema/oss_plugins.json';
|
||||||
import { assertTelemetryPayload, flatKeys } from './utils';
|
import { assertTelemetryPayload, flatKeys } from './utils';
|
||||||
|
|
||||||
|
async function retrieveTelemetry(
|
||||||
|
supertest: supertestAsPromised.SuperTest<supertestAsPromised.Test>
|
||||||
|
) {
|
||||||
|
const { body } = await supertest
|
||||||
|
.post('/api/telemetry/v2/clusters/_stats')
|
||||||
|
.set('kbn-xsrf', 'xxx')
|
||||||
|
.send({ unencrypted: true })
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
expect(body.length).to.be(1);
|
||||||
|
return body[0];
|
||||||
|
}
|
||||||
|
|
||||||
export default function ({ getService }: FtrProviderContext) {
|
export default function ({ getService }: FtrProviderContext) {
|
||||||
const supertest = getService('supertest');
|
const supertest = getService('supertest');
|
||||||
const es = getService('es');
|
const es = getService('es');
|
||||||
|
@ -35,14 +49,7 @@ export default function ({ getService }: FtrProviderContext) {
|
||||||
let stats: Record<string, any>;
|
let stats: Record<string, any>;
|
||||||
|
|
||||||
before('pull local stats', async () => {
|
before('pull local stats', async () => {
|
||||||
const { body } = await supertest
|
stats = await retrieveTelemetry(supertest);
|
||||||
.post('/api/telemetry/v2/clusters/_stats')
|
|
||||||
.set('kbn-xsrf', 'xxx')
|
|
||||||
.send({ unencrypted: true })
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body.length).to.be(1);
|
|
||||||
stats = body[0];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should pass the schema validation', () => {
|
it('should pass the schema validation', () => {
|
||||||
|
@ -141,14 +148,7 @@ export default function ({ getService }: FtrProviderContext) {
|
||||||
before('Add UI Counters saved objects', () => esArchiver.load('saved_objects/ui_counters'));
|
before('Add UI Counters saved objects', () => esArchiver.load('saved_objects/ui_counters'));
|
||||||
after('cleanup saved objects changes', () => esArchiver.unload('saved_objects/ui_counters'));
|
after('cleanup saved objects changes', () => esArchiver.unload('saved_objects/ui_counters'));
|
||||||
it('returns ui counters aggregated by day', async () => {
|
it('returns ui counters aggregated by day', async () => {
|
||||||
const { body } = await supertest
|
const stats = await retrieveTelemetry(supertest);
|
||||||
.post('/api/telemetry/v2/clusters/_stats')
|
|
||||||
.set('kbn-xsrf', 'xxx')
|
|
||||||
.send({ unencrypted: true })
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body.length).to.be(1);
|
|
||||||
const stats = body[0];
|
|
||||||
expect(stats.stack_stats.kibana.plugins.ui_counters).to.eql(basicUiCounters);
|
expect(stats.stack_stats.kibana.plugins.ui_counters).to.eql(basicUiCounters);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -191,14 +191,7 @@ export default function ({ getService }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return application_usage data', async () => {
|
it('should return application_usage data', async () => {
|
||||||
const { body } = await supertest
|
const stats = await retrieveTelemetry(supertest);
|
||||||
.post('/api/telemetry/v2/clusters/_stats')
|
|
||||||
.set('kbn-xsrf', 'xxx')
|
|
||||||
.send({ unencrypted: true })
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body.length).to.be(1);
|
|
||||||
const stats = body[0];
|
|
||||||
expect(stats.stack_stats.kibana.plugins.application_usage).to.eql({
|
expect(stats.stack_stats.kibana.plugins.application_usage).to.eql({
|
||||||
'test-app': {
|
'test-app': {
|
||||||
appId: 'test-app',
|
appId: 'test-app',
|
||||||
|
@ -262,14 +255,7 @@ export default function ({ getService }: FtrProviderContext) {
|
||||||
|
|
||||||
// flaky https://github.com/elastic/kibana/issues/94513
|
// flaky https://github.com/elastic/kibana/issues/94513
|
||||||
it.skip("should only use the first 10k docs for the application_usage data (they'll be rolled up in a later process)", async () => {
|
it.skip("should only use the first 10k docs for the application_usage data (they'll be rolled up in a later process)", async () => {
|
||||||
const { body } = await supertest
|
const stats = await retrieveTelemetry(supertest);
|
||||||
.post('/api/telemetry/v2/clusters/_stats')
|
|
||||||
.set('kbn-xsrf', 'xxx')
|
|
||||||
.send({ unencrypted: true })
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body.length).to.be(1);
|
|
||||||
const stats = body[0];
|
|
||||||
expect(stats.stack_stats.kibana.plugins.application_usage).to.eql({
|
expect(stats.stack_stats.kibana.plugins.application_usage).to.eql({
|
||||||
'test-app': {
|
'test-app': {
|
||||||
appId: 'test-app',
|
appId: 'test-app',
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { StatsGetter } from 'src/plugins/telemetry_collection_manager/server';
|
||||||
import { TelemetryLocalStats, getLocalStats } from '../../../../../src/plugins/telemetry/server';
|
import { TelemetryLocalStats, getLocalStats } from '../../../../../src/plugins/telemetry/server';
|
||||||
import { getXPackUsage } from './get_xpack';
|
import { getXPackUsage } from './get_xpack';
|
||||||
import { ESLicense, getLicenseFromLocalOrMaster } from './get_license';
|
import { ESLicense, getLicenseFromLocalOrMaster } from './get_license';
|
||||||
|
import { isClusterOptedIn } from './is_cluster_opted_in';
|
||||||
|
|
||||||
export type TelemetryAggregatedStats = TelemetryLocalStats & {
|
export type TelemetryAggregatedStats = TelemetryLocalStats & {
|
||||||
stack_stats: { xpack?: object };
|
stack_stats: { xpack?: object };
|
||||||
|
@ -48,6 +49,10 @@ export const getStatsWithXpack: StatsGetter<TelemetryAggregatedStats> = async fu
|
||||||
if (monitoringTelemetry) {
|
if (monitoringTelemetry) {
|
||||||
delete stats.stack_stats.kibana!.plugins.monitoringTelemetry;
|
delete stats.stack_stats.kibana!.plugins.monitoringTelemetry;
|
||||||
}
|
}
|
||||||
return [...acc, stats, ...(monitoringTelemetry || [])];
|
|
||||||
|
// From the monitoring-sourced telemetry, we need to filter out the clusters that are opted-out.
|
||||||
|
const onlyOptedInMonitoringClusters = (monitoringTelemetry || []).filter(isClusterOptedIn);
|
||||||
|
|
||||||
|
return [...acc, stats, ...onlyOptedInMonitoringClusters];
|
||||||
}, [] as TelemetryAggregatedStats[]);
|
}, [] as TelemetryAggregatedStats[]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
* 2.0.
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isClusterOptedIn } from './util';
|
import { isClusterOptedIn } from './is_cluster_opted_in';
|
||||||
|
|
||||||
const createMockClusterUsage = (plugins: any) => {
|
const createMockClusterUsage = (plugins: any) => {
|
||||||
return {
|
return {
|
||||||
|
@ -32,9 +31,9 @@ describe('isClusterOptedIn', () => {
|
||||||
const result = isClusterOptedIn(mockClusterUsage);
|
const result = isClusterOptedIn(mockClusterUsage);
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
});
|
});
|
||||||
it('returns false if cluster stats is malformed', () => {
|
it('returns true if kibana.plugins.telemetry does not exist', () => {
|
||||||
expect(isClusterOptedIn(createMockClusterUsage({}))).toBe(false);
|
expect(isClusterOptedIn(createMockClusterUsage({}))).toBe(true);
|
||||||
expect(isClusterOptedIn({})).toBe(false);
|
expect(isClusterOptedIn({})).toBe(true);
|
||||||
expect(isClusterOptedIn(undefined)).toBe(false);
|
expect(isClusterOptedIn(undefined)).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const isClusterOptedIn = (clusterUsage: any): boolean => {
|
||||||
|
return (
|
||||||
|
clusterUsage?.stack_stats?.kibana?.plugins?.telemetry?.opt_in_status === true ||
|
||||||
|
// If stack_stats.kibana.plugins.telemetry does not exist, assume opted-in for BWC
|
||||||
|
!clusterUsage?.stack_stats?.kibana?.plugins?.telemetry
|
||||||
|
);
|
||||||
|
};
|
Loading…
Reference in a new issue