-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[APM] Script for creating functional test archive (#76926)
* [APM] Script for creating functional test archive * Lock down variables; add documentation * Update tests
- Loading branch information
1 parent
87380f5
commit 2a451c9
Showing
15 changed files
with
127,018 additions
and
45 deletions.
There are no files selected for viewing
8 changes: 8 additions & 0 deletions
8
x-pack/plugins/apm/dev_docs/updating_functional_tests_archives.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
### Updating functional tests archives | ||
|
||
Some of our API tests use an archive generated by the [`esarchiver`](https://www.elastic.co/guide/en/kibana/current/development-functional-tests.html) script. Updating the main archive (`apm_8.0.0`) is a scripted process, where a 30m snapshot is downloaded from a cluster running the [APM Integration Testing server](https://github.com/elastic/apm-integration-testing). The script will copy the generated archives into the `fixtures/es_archiver` folders of our test suites (currently `basic` and `trial`). It will also generate a file that contains metadata about the archive, that can be imported to get the time range of the snapshot. | ||
|
||
Usage: | ||
`node x-pack/plugins/apm/scripts/create-functional-tests-archive --es-url=https://admin:changeme@localhost:9200 --kibana-url=https://localhost:5601` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
x-pack/plugins/apm/scripts/create-functional-tests-archive.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
// compile typescript on the fly | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
require('@babel/register')({ | ||
extensions: ['.js', '.ts'], | ||
plugins: ['@babel/plugin-proposal-optional-chaining'], | ||
presets: [ | ||
'@babel/typescript', | ||
['@babel/preset-env', { targets: { node: 'current' } }], | ||
], | ||
}); | ||
|
||
require('./create-functional-tests-archive/index.ts'); |
179 changes: 179 additions & 0 deletions
179
x-pack/plugins/apm/scripts/create-functional-tests-archive/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { argv } from 'yargs'; | ||
import { execSync } from 'child_process'; | ||
import moment from 'moment'; | ||
import path from 'path'; | ||
import fs from 'fs'; | ||
import { stampLogger } from '../shared/stamp-logger'; | ||
|
||
async function run() { | ||
stampLogger(); | ||
|
||
const archiveName = 'apm_8.0.0'; | ||
|
||
// include important APM data and ML data | ||
const indices = | ||
'apm-*-transaction,apm-*-span,apm-*-error,apm-*-metric,.ml-anomalies*,.ml-config'; | ||
|
||
const esUrl = argv['es-url'] as string | undefined; | ||
|
||
if (!esUrl) { | ||
throw new Error('--es-url is not set'); | ||
} | ||
const kibanaUrl = argv['kibana-url'] as string | undefined; | ||
|
||
if (!kibanaUrl) { | ||
throw new Error('--kibana-url is not set'); | ||
} | ||
const gte = moment().subtract(1, 'hour').toISOString(); | ||
const lt = moment(gte).add(30, 'minutes').toISOString(); | ||
|
||
// eslint-disable-next-line no-console | ||
console.log(`Archiving from ${gte} to ${lt}...`); | ||
|
||
// APM data uses '@timestamp' (ECS), ML data uses 'timestamp' | ||
|
||
const rangeQueries = [ | ||
{ | ||
range: { | ||
'@timestamp': { | ||
gte, | ||
lt, | ||
}, | ||
}, | ||
}, | ||
{ | ||
range: { | ||
timestamp: { | ||
gte, | ||
lt, | ||
}, | ||
}, | ||
}, | ||
]; | ||
|
||
// some of the data is timeless/content | ||
const query = { | ||
bool: { | ||
should: [ | ||
...rangeQueries, | ||
{ | ||
bool: { | ||
must_not: [ | ||
{ | ||
exists: { | ||
field: '@timestamp', | ||
}, | ||
}, | ||
{ | ||
exists: { | ||
field: 'timestamp', | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
], | ||
minimum_should_match: 1, | ||
}, | ||
}; | ||
|
||
const archivesDir = path.join(__dirname, '.archives'); | ||
const root = path.join(__dirname, '../../../../..'); | ||
|
||
// create the archive | ||
|
||
execSync( | ||
`node scripts/es_archiver save ${archiveName} ${indices} --dir=${archivesDir} --kibana-url=${kibanaUrl} --es-url=${esUrl} --query='${JSON.stringify( | ||
query | ||
)}'`, | ||
{ | ||
cwd: root, | ||
stdio: 'inherit', | ||
} | ||
); | ||
|
||
const targetDirs = ['trial', 'basic']; | ||
|
||
// copy the archives to the test fixtures | ||
|
||
await Promise.all( | ||
targetDirs.map(async (target) => { | ||
const targetPath = path.resolve( | ||
__dirname, | ||
'../../../../test/apm_api_integration/', | ||
target | ||
); | ||
const targetArchivesPath = path.resolve( | ||
targetPath, | ||
'fixtures/es_archiver', | ||
archiveName | ||
); | ||
|
||
if (!fs.existsSync(targetArchivesPath)) { | ||
fs.mkdirSync(targetArchivesPath); | ||
} | ||
|
||
fs.copyFileSync( | ||
path.join(archivesDir, archiveName, 'data.json.gz'), | ||
path.join(targetArchivesPath, 'data.json.gz') | ||
); | ||
fs.copyFileSync( | ||
path.join(archivesDir, archiveName, 'mappings.json'), | ||
path.join(targetArchivesPath, 'mappings.json') | ||
); | ||
|
||
const currentConfig = {}; | ||
|
||
// get the current metadata and extend/override metadata for the new archive | ||
const configFilePath = path.join(targetPath, 'archives_metadata.ts'); | ||
|
||
try { | ||
Object.assign(currentConfig, (await import(configFilePath)).default); | ||
} catch (error) { | ||
// do nothing | ||
} | ||
|
||
const newConfig = { | ||
...currentConfig, | ||
[archiveName]: { | ||
start: gte, | ||
end: lt, | ||
}, | ||
}; | ||
|
||
fs.writeFileSync( | ||
configFilePath, | ||
`export default ${JSON.stringify(newConfig, null, 2)}`, | ||
{ encoding: 'utf-8' } | ||
); | ||
}) | ||
); | ||
|
||
fs.unlinkSync(path.join(archivesDir, archiveName, 'data.json.gz')); | ||
fs.unlinkSync(path.join(archivesDir, archiveName, 'mappings.json')); | ||
fs.rmdirSync(path.join(archivesDir, archiveName)); | ||
fs.rmdirSync(archivesDir); | ||
|
||
// run ESLint on the generated metadata files | ||
|
||
execSync('node scripts/eslint **/*/archives_metadata.ts --fix', { | ||
cwd: root, | ||
stdio: 'inherit', | ||
}); | ||
} | ||
|
||
run() | ||
.then(() => { | ||
process.exit(0); | ||
}) | ||
.catch((err) => { | ||
// eslint-disable-next-line no-console | ||
console.log(err); | ||
process.exit(1); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { Client } from '@elastic/elasticsearch'; | ||
import { ApiKeyAuth, BasicAuth } from '@elastic/elasticsearch/lib/pool'; | ||
import { ESSearchResponse, ESSearchRequest } from '../../typings/elasticsearch'; | ||
|
||
export type ESClient = ReturnType<typeof getEsClient>; | ||
|
||
export function getEsClient({ | ||
node, | ||
auth, | ||
}: { | ||
node: string; | ||
auth?: BasicAuth | ApiKeyAuth; | ||
}) { | ||
const client = new Client({ | ||
node, | ||
ssl: { | ||
rejectUnauthorized: false, | ||
}, | ||
requestTimeout: 120000, | ||
auth, | ||
}); | ||
|
||
return { | ||
...client, | ||
async search<TDocument, TSearchRequest extends ESSearchRequest>( | ||
request: TSearchRequest | ||
) { | ||
const response = await client.search(request as any); | ||
|
||
return { | ||
...response, | ||
body: response.body as ESSearchResponse<TDocument, TSearchRequest>, | ||
}; | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { parse, format } from 'url'; | ||
|
||
export function parseIndexUrl(url: string): { node: string; index: string } { | ||
const parsed = parse(url); | ||
const { pathname, ...rest } = parsed; | ||
|
||
return { | ||
node: format(rest), | ||
index: pathname!.replace('/', ''), | ||
}; | ||
} |
12 changes: 12 additions & 0 deletions
12
x-pack/test/apm_api_integration/basic/archives_metadata.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
export default { | ||
'apm_8.0.0': { | ||
start: '2020-09-09T06:11:22.998Z', | ||
end: '2020-09-09T06:41:22.998Z', | ||
}, | ||
}; |
Binary file added
BIN
+1.21 MB
x-pack/test/apm_api_integration/basic/fixtures/es_archiver/apm_8.0.0/data.json.gz
Binary file not shown.
Oops, something went wrong.