[QA][SO INFO SVC] Add cli (#108353)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Tre 2021-08-16 13:36:22 +01:00 committed by GitHub
parent a5e97fc21e
commit 8a571c2f7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 189 additions and 63 deletions

View file

@ -0,0 +1,10 @@
/*
* 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.
*/
require('../src/setup_node_env');
require('../test/common/services/saved_object_info').runSavedObjInfoSvc();

View file

@ -1,63 +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.
*/
import { inspect } from 'util';
import type { estypes } from '@elastic/elasticsearch';
import { ToolingLog } from '@kbn/dev-utils';
import { FtrService } from '../ftr_provider_context';
export class SavedObjectInfoService extends FtrService {
private readonly es = this.ctx.getService('es');
public async logSoTypes(log: ToolingLog, msg: string | null = null) {
const types = await this.getTypes();
log.debug(
`\n### Saved Object Types ${msg || 'Count: ' + types.length}\n${inspect(types, {
compact: false,
depth: 99,
breakLength: 80,
sorted: true,
})}`
);
}
public async getTypes(index = '.kibana') {
try {
const { body } = await this.es.search({
index,
size: 0,
body: {
aggs: {
savedobjs: {
terms: {
field: 'type',
},
},
},
},
});
const agg = body.aggregations?.savedobjs as
| estypes.AggregationsTermsAggregate<{ key: string; doc_count: number }>
| undefined;
if (!agg?.buckets) {
throw new Error(
`expected es to return buckets of saved object types: ${inspect(body, { depth: 100 })}`
);
}
return agg.buckets;
} catch (error) {
throw new Error(`Error while searching for saved object types: ${error}`);
}
}
}

View file

@ -0,0 +1,38 @@
/*
* 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.
*/
import { run } from '@kbn/dev-utils';
import { pipe } from 'fp-ts/function';
import { payload, noop, areValid, print, expectedFlags } from './utils';
import { types } from './saved_object_info';
export { SavedObjectInfoService } from './saved_object_info';
export const runSavedObjInfoSvc = () =>
run(
async ({ flags, log }) => {
const printWith = print(log);
const getAndFormatAndPrint = async () =>
pipe(await types(flags.esUrl as string)(), payload, printWith());
return areValid(flags) ? getAndFormatAndPrint() : noop();
},
{
description: `
Show information pertaining to the saved objects in the .kibana index
Examples:
See 'saved_objects_info_svc.md'
`,
flags: expectedFlags(),
}
);

View file

@ -0,0 +1,63 @@
/*
* 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.
*/
import { Client } from '@elastic/elasticsearch';
import url from 'url';
import { Either, fromNullable, chain, getOrElse, toError } from 'fp-ts/Either';
import { flow, pipe } from 'fp-ts/function';
import * as TE from 'fp-ts/lib/TaskEither';
import * as T from 'fp-ts/lib/Task';
import { ToolingLog } from '@kbn/dev-utils';
import { FtrService } from '../../ftr_provider_context';
import { print } from './utils';
const pluck = (key: string) => (obj: any): Either<Error, string> =>
fromNullable(new Error(`Missing ${key}`))(obj[key]);
const query = {
aggs: {
savedobjs: {
terms: {
field: 'type',
},
},
},
};
export const types = (node: string) => async (index: string = '.kibana') =>
await pipe(
TE.tryCatch(
async () => {
const { body } = await new Client({ node }).search({
index,
size: 0,
body: query,
});
return body;
},
(reason: any) => toError(reason)
),
TE.map((resp: any) =>
flow(
pluck('aggregations'),
chain(pluck('savedobjs')),
chain(pluck('buckets')),
getOrElse((err: Error) => err.message)
)(resp)
),
TE.fold((x) => T.of(`Error while searching for saved object types: ${x}`), T.of)
)();
export class SavedObjectInfoService extends FtrService {
private readonly config = this.ctx.getService('config');
public async logSoTypes(log: ToolingLog, msg: string | null = null) {
// @ts-ignore
pipe(await types(url.format(this.config.get('servers.elasticsearch'))), print(log)(msg));
}
}

View file

@ -0,0 +1,35 @@
# Saved Objects Info Svc w/ CLI
## Used via the cli
Run the cli
> the **--esUrl** arg is required; tells the svc which elastic search endpoint to use
```shell
λ node scripts/saved_objs_info.js --esUrl http://elastic:changeme@localhost:9220 --soTypes
```
Result
```shell
### types:
[
{
doc_count: 5,
key: 'canvas-workpad-template'
},
{
doc_count: 1,
key: 'apm-telemetry'
},
{
doc_count: 1,
key: 'config'
},
{
doc_count: 1,
key: 'space'
}
]
```

View file

@ -0,0 +1,43 @@
/*
* 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.
*/
import { inspect } from 'util';
import { createFlagError, ToolingLog } from '@kbn/dev-utils';
export const format = (obj: unknown) =>
inspect(obj, {
compact: false,
depth: 99,
breakLength: 80,
sorted: true,
});
export const noop = () => {};
export const areValid = (flags: any) => {
if (flags.esUrl === '') throw createFlagError('please provide a single --esUrl flag');
return true;
};
// @ts-ignore
export const print = (log: ToolingLog) => (msg: string | null = null) => ({ xs, count }) =>
log.success(`\n### Saved Object Types ${msg || 'Count: ' + count}\n${xs}`);
export const expectedFlags = () => ({
string: ['esUrl'],
boolean: ['soTypes'],
help: `
--esUrl Required, tells the app which url to point to
--soTypes Not Required, tells the svc to show the types within the .kibana index
`,
});
export const payload = (xs: any) => ({
xs: format(xs),
count: xs.length,
});