From a699cf016f40c760239cbc38d0fff52c2edc452c Mon Sep 17 00:00:00 2001 From: "miriam.aparicio" Date: Tue, 12 Nov 2024 12:18:29 +0000 Subject: [PATCH 1/2] Migrate APM infra tests to agnostic deployment tests --- .../apis/observability/apm/index.ts | 1 + .../apm/infrastructure/generate_data.ts | 53 ++++++++++++ .../observability/apm/infrastructure/index.ts | 14 ++++ .../infrastructure_attributes.spec.ts | 80 +++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/generate_data.ts create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/index.ts create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/infrastructure_attributes.spec.ts diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/index.ts index cc56d0f2e6684..4e8262e3b1bcd 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/index.ts @@ -20,5 +20,6 @@ export default function apmApiIntegrationTests({ loadTestFile(require.resolve('./correlations')); loadTestFile(require.resolve('./entities')); loadTestFile(require.resolve('./cold_start')); + loadTestFile(require.resolve('./infrastructure')); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/generate_data.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/generate_data.ts new file mode 100644 index 0000000000000..437c4791e1972 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/generate_data.ts @@ -0,0 +1,53 @@ +/* + * 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 { apm, timerange } from '@kbn/apm-synthtrace-client'; +import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; + +export async function generateData({ + apmSynthtraceEsClient, + start, + end, +}: { + apmSynthtraceEsClient: ApmSynthtraceEsClient; + start: number; + end: number; +}) { + const serviceRunsInContainerInstance = apm + .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) + .instance('instance-a'); + + const serviceInstance = apm + .service({ name: 'synth-java', environment: 'production', agentName: 'java' }) + .instance('instance-b'); + + await apmSynthtraceEsClient.index( + timerange(start, end) + .interval('1m') + .generator((timestamp) => { + return [ + serviceRunsInContainerInstance + .transaction({ transactionName: 'GET /apple 🍎' }) + .defaults({ + 'container.id': 'foo', + 'host.hostname': 'bar', + 'kubernetes.pod.name': 'baz', + }) + .timestamp(timestamp) + .duration(1000) + .success(), + serviceInstance + .transaction({ transactionName: 'GET /banana 🍌' }) + .defaults({ + 'host.hostname': 'bar', + }) + .timestamp(timestamp) + .duration(1000) + .success(), + ]; + }) + ); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/index.ts new file mode 100644 index 0000000000000..1351a44d41c8e --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/index.ts @@ -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. + */ + +import { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) { + describe('infrastructure', () => { + loadTestFile(require.resolve('./infrastructure_attributes.spec.ts')); + }); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/infrastructure_attributes.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/infrastructure_attributes.spec.ts new file mode 100644 index 0000000000000..b9f02fe9deabd --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/infrastructure_attributes.spec.ts @@ -0,0 +1,80 @@ +/* + * 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 '@kbn/expect'; +import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import { generateData } from './generate_data'; +import { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + const synthtrace = getService('synthtrace'); + + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + + async function callApi(serviceName: string) { + const response = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/infrastructure_attributes', + params: { + path: { + serviceName, + }, + query: { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + environment: 'ENVIRONMENT_ALL', + kuery: '', + }, + }, + }); + return response; + } + + describe('Infrastructure APM API', () => { + describe('Infrastructure attributes when data is not loaded', () => { + it('handles the empty state', async () => { + const response = await callApi('synth-go'); + expect(response.status).to.be(200); + expect(response.body.containerIds.length).to.be(0); + expect(response.body.hostNames.length).to.be(0); + expect(response.body.podNames.length).to.be(0); + }); + }); + + describe('Infrastructure attributes', () => { + describe('when data is loaded', () => { + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + beforeEach(async () => { + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); + await generateData({ start, end, apmSynthtraceEsClient }); + }); + + afterEach(() => apmSynthtraceEsClient.clean()); + + describe('when service runs in container', () => { + it('returns arrays of container ids and pod names', async () => { + const response = await callApi('synth-go'); + expect(response.status).to.be(200); + expect(response.body.containerIds.length).to.be(1); + expect(response.body.hostNames.length).to.be(1); + expect(response.body.podNames.length).to.be(1); + }); + }); + + describe('when service does NOT run in container', () => { + it('returns array of host names', async () => { + const response = await callApi('synth-java'); + expect(response.status).to.be(200); + expect(response.body.containerIds.length).to.be(0); + expect(response.body.hostNames.length).to.be(1); + expect(response.body.podNames.length).to.be(0); + }); + }); + }); + }); + }); +} From 8f3e0753e476867bb7019f797c146f5dabda1bf1 Mon Sep 17 00:00:00 2001 From: "miriam.aparicio" Date: Tue, 12 Nov 2024 12:40:44 +0000 Subject: [PATCH 2/2] move files instead of delete/copy --- .../infrastructure_attributes.spec.ts | 49 ++++++----- .../tests/infrastructure/generate_data.ts | 53 ------------ .../infrastructure_attributes.spec.ts | 81 ------------------- 3 files changed, 24 insertions(+), 159 deletions(-) delete mode 100644 x-pack/test/apm_api_integration/tests/infrastructure/generate_data.ts delete mode 100644 x-pack/test/apm_api_integration/tests/infrastructure/infrastructure_attributes.spec.ts diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/infrastructure_attributes.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/infrastructure_attributes.spec.ts index b9f02fe9deabd..ca70d8d1fa002 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/infrastructure_attributes.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/infrastructure/infrastructure_attributes.spec.ts @@ -34,7 +34,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon return response; } - describe('Infrastructure APM API', () => { + describe('Infrastructure attributes', () => { describe('Infrastructure attributes when data is not loaded', () => { it('handles the empty state', async () => { const response = await callApi('synth-go'); @@ -45,34 +45,33 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); }); - describe('Infrastructure attributes', () => { - describe('when data is loaded', () => { - let apmSynthtraceEsClient: ApmSynthtraceEsClient; - beforeEach(async () => { - apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); - await generateData({ start, end, apmSynthtraceEsClient }); - }); + describe('when data is loaded', () => { + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + + before(async () => { + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); + await generateData({ start, end, apmSynthtraceEsClient }); + }); - afterEach(() => apmSynthtraceEsClient.clean()); + after(() => apmSynthtraceEsClient.clean()); - describe('when service runs in container', () => { - it('returns arrays of container ids and pod names', async () => { - const response = await callApi('synth-go'); - expect(response.status).to.be(200); - expect(response.body.containerIds.length).to.be(1); - expect(response.body.hostNames.length).to.be(1); - expect(response.body.podNames.length).to.be(1); - }); + describe('when service runs in container', () => { + it('returns arrays of container ids and pod names', async () => { + const response = await callApi('synth-go'); + expect(response.status).to.be(200); + expect(response.body.containerIds.length).to.be(1); + expect(response.body.hostNames.length).to.be(1); + expect(response.body.podNames.length).to.be(1); }); + }); - describe('when service does NOT run in container', () => { - it('returns array of host names', async () => { - const response = await callApi('synth-java'); - expect(response.status).to.be(200); - expect(response.body.containerIds.length).to.be(0); - expect(response.body.hostNames.length).to.be(1); - expect(response.body.podNames.length).to.be(0); - }); + describe('when service does NOT run in container', () => { + it('returns array of host names', async () => { + const response = await callApi('synth-java'); + expect(response.status).to.be(200); + expect(response.body.containerIds.length).to.be(0); + expect(response.body.hostNames.length).to.be(1); + expect(response.body.podNames.length).to.be(0); }); }); }); diff --git a/x-pack/test/apm_api_integration/tests/infrastructure/generate_data.ts b/x-pack/test/apm_api_integration/tests/infrastructure/generate_data.ts deleted file mode 100644 index 437c4791e1972..0000000000000 --- a/x-pack/test/apm_api_integration/tests/infrastructure/generate_data.ts +++ /dev/null @@ -1,53 +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 { apm, timerange } from '@kbn/apm-synthtrace-client'; -import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; - -export async function generateData({ - apmSynthtraceEsClient, - start, - end, -}: { - apmSynthtraceEsClient: ApmSynthtraceEsClient; - start: number; - end: number; -}) { - const serviceRunsInContainerInstance = apm - .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) - .instance('instance-a'); - - const serviceInstance = apm - .service({ name: 'synth-java', environment: 'production', agentName: 'java' }) - .instance('instance-b'); - - await apmSynthtraceEsClient.index( - timerange(start, end) - .interval('1m') - .generator((timestamp) => { - return [ - serviceRunsInContainerInstance - .transaction({ transactionName: 'GET /apple 🍎' }) - .defaults({ - 'container.id': 'foo', - 'host.hostname': 'bar', - 'kubernetes.pod.name': 'baz', - }) - .timestamp(timestamp) - .duration(1000) - .success(), - serviceInstance - .transaction({ transactionName: 'GET /banana 🍌' }) - .defaults({ - 'host.hostname': 'bar', - }) - .timestamp(timestamp) - .duration(1000) - .success(), - ]; - }) - ); -} diff --git a/x-pack/test/apm_api_integration/tests/infrastructure/infrastructure_attributes.spec.ts b/x-pack/test/apm_api_integration/tests/infrastructure/infrastructure_attributes.spec.ts deleted file mode 100644 index 7a79e2f8be4b1..0000000000000 --- a/x-pack/test/apm_api_integration/tests/infrastructure/infrastructure_attributes.spec.ts +++ /dev/null @@ -1,81 +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 '@kbn/expect'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { generateData } from './generate_data'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); - const apmSynthtraceEsClient = getService('apmSynthtraceEsClient'); - - const start = new Date('2021-01-01T00:00:00.000Z').getTime(); - const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; - - async function callApi(serviceName: string) { - const response = await apmApiClient.readUser({ - endpoint: 'GET /internal/apm/services/{serviceName}/infrastructure_attributes', - params: { - path: { - serviceName, - }, - query: { - start: new Date(start).toISOString(), - end: new Date(end).toISOString(), - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }, - }); - return response; - } - - registry.when( - 'Infrastructure attributes when data is not loaded', - { config: 'basic', archives: [] }, - () => { - it('handles the empty state', async () => { - const response = await callApi('synth-go'); - expect(response.status).to.be(200); - expect(response.body.containerIds.length).to.be(0); - expect(response.body.hostNames.length).to.be(0); - expect(response.body.podNames.length).to.be(0); - }); - } - ); - - // FLAKY: https://github.com/elastic/kibana/issues/177386 - registry.when('Infrastructure attributes', { config: 'basic', archives: [] }, () => { - describe('when data is loaded', () => { - beforeEach(async () => { - await generateData({ start, end, apmSynthtraceEsClient }); - }); - - afterEach(() => apmSynthtraceEsClient.clean()); - - describe('when service runs in container', () => { - it('returns arrays of container ids and pod names', async () => { - const response = await callApi('synth-go'); - expect(response.status).to.be(200); - expect(response.body.containerIds.length).to.be(1); - expect(response.body.hostNames.length).to.be(1); - expect(response.body.podNames.length).to.be(1); - }); - }); - - describe('when service does NOT run in container', () => { - it('returns array of host names', async () => { - const response = await callApi('synth-java'); - expect(response.status).to.be(200); - expect(response.body.containerIds.length).to.be(0); - expect(response.body.hostNames.length).to.be(1); - expect(response.body.podNames.length).to.be(0); - }); - }); - }); - }); -}