Skip to content

Commit

Permalink
refactoring and adding test
Browse files Browse the repository at this point in the history
  • Loading branch information
cauemarcondes committed Jun 16, 2021
1 parent 708dfa8 commit 534bc7c
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { APMPluginStartDependencies } from '../../types';
import { ExternalCallback } from '../../../../fleet/server';
import { AGENT_NAME } from '../../../common/elasticsearch_fieldnames';
import { AgentConfiguration } from '../../../common/agent_configuration/configuration_types';
import { getPackagePolicyWithSourceMap, listArtifacts } from './source_maps';

export async function registerFleetPolicyCallbacks({
plugins,
Expand All @@ -31,7 +32,7 @@ export async function registerFleetPolicyCallbacks({

// Registers a callback invoked when a policy is created to populate the APM
// integration policy with pre-existing agent configurations
registerAgentConfigExternalCallback({
registerPackagePolicyExternalCallback({
fleetPluginStart,
callbackName: 'packagePolicyCreate',
plugins,
Expand All @@ -42,7 +43,7 @@ export async function registerFleetPolicyCallbacks({

// Registers a callback invoked when a policy is updated to populate the APM
// integration policy with existing agent configurations
registerAgentConfigExternalCallback({
registerPackagePolicyExternalCallback({
fleetPluginStart,
callbackName: 'packagePolicyUpdate',
plugins,
Expand All @@ -53,11 +54,11 @@ export async function registerFleetPolicyCallbacks({
}

type ExternalCallbackParams = Parameters<ExternalCallback[1]>;
type PackagePolicy = ExternalCallbackParams[0];
export type PackagePolicy = ExternalCallbackParams[0];
type Context = ExternalCallbackParams[1];
type Request = ExternalCallbackParams[2];

function registerAgentConfigExternalCallback({
function registerPackagePolicyExternalCallback({
fleetPluginStart,
callbackName,
plugins,
Expand Down Expand Up @@ -91,16 +92,23 @@ function registerAgentConfigExternalCallback({
ruleDataClient,
});
const agentConfigurations = await listConfigurations({ setup });
return getPackagePolicyWithAgentConfigurations(
packagePolicy,
agentConfigurations
);
const artifacts = await listArtifacts({ fleetPluginStart });
return {
...getPackagePolicyWithAgentConfigurations(
packagePolicy,
agentConfigurations
),
...getPackagePolicyWithSourceMap({
packagePolicy,
artifacts,
}),
};
};

fleetPluginStart.registerExternalCallback(callbackName, callbackFn);
}

const APM_SERVER = 'apm-server';
export const APM_SERVER = 'apm-server';

// Immutable function applies the given package policy with a set of agent configurations
export function getPackagePolicyWithAgentConfigurations(
Expand Down
173 changes: 173 additions & 0 deletions x-pack/plugins/apm/server/lib/fleet/source_maps.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*
* 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 { SavedObjectsClientContract, ElasticsearchClient } from 'kibana/server';
import {
ArtifactSourceMap,
getPackagePolicyWithSourceMap,
updateSourceMapsOnFleetPolicies,
FleetPluginStart,
} from './source_maps';

const packagePolicy = {
id: '123',
version: 'WzMxNDI2LDFd',
name: 'apm-1',
description: '',
namespace: 'default',
policy_id: '7a87c160-c961-11eb-81e2-f7327d61c92a',
enabled: true,
output_id: '',
inputs: [
{
policy_template: 'apmserver',
streams: [],
vars: {},
type: 'apm',
enabled: true,
compiled_input: {
'apm-server': {
capture_personal_data: true,
max_event_size: 307200,
api_key: { limit: 100, enabled: false },
default_service_environment: null,
host: 'localhost:8200',
kibana: { api_key: null },
secret_token: null,
},
},
},
],
package: { name: 'apm', title: 'Elastic APM', version: '0.2.0' },
created_at: '2021-06-16T14:54:32.195Z',
created_by: 'elastic',
};

const artifacts = [
{
type: 'sourcemap',
identifier: 'service_name-1.0.0',
relative_url: '/api/fleet/artifacts/service_name-1.0.0/my-id-1',
body: {
serviceName: 'service_name',
serviceVersion: '1.0.0',
bundleFilepath: 'http://localhost:3000/static/js/main.chunk.js',
sourceMap: {
version: 3,
file: 'static/js/main.chunk.js',
sources: ['foo'],
sourcesContent: ['foo'],
mappings: 'foo',
sourceRoot: '',
},
},
created: '2021-06-16T15:03:55.049Z',
id: 'apm:service_name-1.0.0-my-id-1',
compressionAlgorithm: 'zlib',
decodedSha256: 'my-id-1',
decodedSize: 9440,
encodedSha256: 'sha123',
encodedSize: 2622,
encryptionAlgorithm: 'none',
packageName: 'apm',
},
{
type: 'sourcemap',
identifier: 'service_name-2.0.0',
relative_url: '/api/fleet/artifacts/service_name-2.0.0/my-id-2',
body: {
serviceName: 'service_name',
serviceVersion: '2.0.0',
bundleFilepath: 'http://localhost:3000/static/js/main.chunk.js',
sourceMap: {
version: 3,
file: 'static/js/main.chunk.js',
sources: ['foo'],
sourcesContent: ['foo'],
mappings: 'foo',
sourceRoot: '',
},
},
created: '2021-06-16T15:03:55.049Z',
id: 'apm:service_name-2.0.0-my-id-2',
compressionAlgorithm: 'zlib',
decodedSha256: 'my-id-2',
decodedSize: 9440,
encodedSha256: 'sha456',
encodedSize: 2622,
encryptionAlgorithm: 'none',
packageName: 'apm',
},
] as ArtifactSourceMap[];

describe('Source maps', () => {
describe('getPackagePolicyWithSourceMap', () => {
it('returns unchanged package policy when artifacts is empty', () => {
const updatedPackagePolicy = getPackagePolicyWithSourceMap({
packagePolicy,
artifacts: [],
});
expect(updatedPackagePolicy).toEqual(packagePolicy);
});
it('adds source maps into the package policy', () => {
const updatedPackagePolicy = getPackagePolicyWithSourceMap({
packagePolicy,
artifacts,
});
expect(updatedPackagePolicy.inputs[0].config).toEqual({
'apm-server': {
value: {
rum: {
source_mapping: {
metadata: [
{
'service.name': 'service_name',
'service.version': '1.0.0',
'bundle.filepath':
'http://localhost:3000/static/js/main.chunk.js',
'sourcemap.url':
'/api/fleet/artifacts/service_name-1.0.0/my-id-1',
},
{
'service.name': 'service_name',
'service.version': '2.0.0',
'bundle.filepath':
'http://localhost:3000/static/js/main.chunk.js',
'sourcemap.url':
'/api/fleet/artifacts/service_name-2.0.0/my-id-2',
},
],
},
},
},
},
});
});
});
describe('updateSourceMapsOnFleetPolicies', () => {
it('saves source maps into the package policy', () => {});
it.only('removes source maps from the package policy', () => {
const update = jest.fn();

updateSourceMapsOnFleetPolicies({
fleetPluginStart: ({
createArtifactsClient: jest.fn().mockReturnValue({
listArtifacts: jest.fn().mockReturnValue({ items: [] }),
}),
packagePolicyService: {
update,
list: jest.fn().mockReturnValue({ items: [packagePolicy] }),
},
} as unknown) as FleetPluginStart,
savedObjectsClient: ({} as unknown) as SavedObjectsClientContract,
elasticsearchClient: ({} as unknown) as ElasticsearchClient,
});

expect(update).toHaveBeenCalled();
});
});
});
98 changes: 57 additions & 41 deletions x-pack/plugins/apm/server/lib/fleet/source_maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as t from 'io-ts';
import { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server';
import { promisify } from 'util';
import { unzip } from 'zlib';
import { PackagePolicy, APM_SERVER } from './register_fleet_policy_callbacks';
import { Artifact } from '../../../../fleet/server';
import { sourceMapRt } from '../../routes/source_maps';
import { APMPluginStartDependencies } from '../../types';
Expand All @@ -18,14 +19,14 @@ export interface ApmArtifactBody {
bundleFilepath: string;
sourceMap: t.TypeOf<typeof sourceMapRt>;
}
type ArtifactSourceMap = Omit<Artifact, 'body'> & { body: ApmArtifactBody };
export type ArtifactSourceMap = Omit<Artifact, 'body'> & {
body: ApmArtifactBody;
};

type FleetPluginStart = NonNullable<APMPluginStartDependencies['fleet']>;
export type FleetPluginStart = NonNullable<APMPluginStartDependencies['fleet']>;

const doUnzip = promisify(unzip);

const APM_SERVER = 'apm-server';

function decodeArtifacts(artifacts: Artifact[]): Promise<ArtifactSourceMap[]> {
return Promise.all(
artifacts.map(async (artifact) => {
Expand All @@ -42,7 +43,7 @@ function getApmArtifactClient(fleetPluginStart: FleetPluginStart) {
return fleetPluginStart.createArtifactsClient('apm');
}

export async function getArtifacts({
export async function listArtifacts({
fleetPluginStart,
}: {
fleetPluginStart: FleetPluginStart;
Expand Down Expand Up @@ -83,7 +84,47 @@ export async function deleteApmArtifact({
return apmArtifactClient.deleteArtifact(id);
}

export async function updateSourceMapsToFleetPolicies({
export function getPackagePolicyWithSourceMap({
packagePolicy,
artifacts,
}: {
packagePolicy: PackagePolicy;
artifacts: ArtifactSourceMap[];
}) {
if (!artifacts.length) {
return packagePolicy;
}
const [firstInput, ...restInputs] = packagePolicy.inputs;
return {
...packagePolicy,
inputs: [
{
...firstInput,
config: {
...firstInput.config,
[APM_SERVER]: {
value: {
...firstInput?.config?.[APM_SERVER].value,
rum: {
source_mapping: {
metadata: artifacts.map((artifact) => ({
'service.name': artifact.body.serviceName,
'service.version': artifact.body.serviceVersion,
'bundle.filepath': artifact.body.bundleFilepath,
'sourcemap.url': artifact.relative_url,
})),
},
},
},
},
},
},
...restInputs,
],
};
}

export async function updateSourceMapsOnFleetPolicies({
fleetPluginStart,
savedObjectsClient,
elasticsearchClient,
Expand All @@ -92,57 +133,32 @@ export async function updateSourceMapsToFleetPolicies({
savedObjectsClient: SavedObjectsClientContract;
elasticsearchClient: ElasticsearchClient;
}) {
const artifacts = await getArtifacts({ fleetPluginStart });
const artifacts = await listArtifacts({ fleetPluginStart });

const apmPolicies = await fleetPluginStart.packagePolicyService.list(
const apmFleetPolicies = await fleetPluginStart.packagePolicyService.list(
savedObjectsClient,
{ kuery: 'ingest-package-policies.package.name:apm' }
);

return Promise.all(
apmPolicies.items.map(async (packagePolicy) => {
apmFleetPolicies.items.map(async (item) => {
const {
id,
revision,
updated_at: updatedAt,
updated_by: updatedBy,
...policyRest
} = packagePolicy;

const [firstInput, ...restInputs] = packagePolicy.inputs;
const updatedPackagePolicy = {
...policyRest,
inputs: [
{
...firstInput,
config: {
...firstInput.config,
[APM_SERVER]: {
value: {
...firstInput?.config?.[APM_SERVER].value,
rum: {
source_mapping: {
metadata: artifacts.map((artifact) => ({
'service.name': artifact.body.serviceName,
'service.version': artifact.body.serviceVersion,
'bundle.filepath': artifact.body.bundleFilepath,
'sourcemap.url': artifact.relative_url,
})),
},
},
},
},
},
},
...restInputs,
],
};
...packagePolicy
} = item;

const updatedPackagePolicy = getPackagePolicyWithSourceMap({
packagePolicy,
artifacts,
});

await fleetPluginStart.packagePolicyService.update(
savedObjectsClient,
elasticsearchClient,
id,
// @ts-ignore
updatedPackagePolicy
);
})
Expand Down
Loading

0 comments on commit 534bc7c

Please sign in to comment.