Sort printed mappings and fields in update check CLI (#176493)

## Summary

Close https://github.com/elastic/kibana/issues/168927

Adds a new utility to pretty print and sort JS objects and use this in
the mappings update check CLI for both fields and mappings.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Jean-Louis Leysens 2024-02-08 17:15:42 +01:00 committed by GitHub
parent 086c4690a5
commit 8df472e823
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 3020 additions and 2908 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -10,13 +10,14 @@ import Fsp from 'fs/promises';
import Path from 'path';
import type { SavedObjectsTypeMappingDefinitions } from '@kbn/core-saved-objects-base-server-internal';
import { prettyPrintAndSortKeys } from '@kbn/utils';
export const CURRENT_MAPPINGS_FILE = Path.resolve(__dirname, '../../current_mappings.json');
export const CURRENT_MAPPINGS_FILE_PATH = Path.resolve(__dirname, '../../current_mappings.json');
export async function readCurrentMappings(): Promise<SavedObjectsTypeMappingDefinitions> {
let currentMappingsJson;
try {
currentMappingsJson = await Fsp.readFile(CURRENT_MAPPINGS_FILE, 'utf8');
currentMappingsJson = await Fsp.readFile(CURRENT_MAPPINGS_FILE_PATH, 'utf8');
} catch (error) {
if (error.code === 'ENOENT') {
return {};
@ -28,6 +29,10 @@ export async function readCurrentMappings(): Promise<SavedObjectsTypeMappingDefi
return JSON.parse(currentMappingsJson);
}
export async function updateCurrentMappings(newMappings: SavedObjectsTypeMappingDefinitions) {
await Fsp.writeFile(CURRENT_MAPPINGS_FILE, JSON.stringify(newMappings, null, 2) + '\n', 'utf8');
export async function writeCurrentMappings(newMappings: SavedObjectsTypeMappingDefinitions) {
await Fsp.writeFile(
CURRENT_MAPPINGS_FILE_PATH,
prettyPrintAndSortKeys(newMappings) + '\n',
'utf8'
);
}

View file

@ -13,7 +13,7 @@ import { createTestEsCluster } from '@kbn/test';
import { extractMappingsFromPlugins } from './extract_mappings_from_plugins';
import { checkAdditiveOnlyChange } from './check_additive_only_change';
import { checkIncompatibleMappings } from './check_incompatible_mappings';
import { readCurrentMappings, updateCurrentMappings } from './current_mappings';
import { readCurrentMappings, writeCurrentMappings } from './current_mappings';
export const runMappingsCompatibilityChecks = async ({
fix,
@ -78,7 +78,7 @@ export const runMappingsCompatibilityChecks = async ({
}
if (fix) {
await updateCurrentMappings(extractedMappings);
await writeCurrentMappings(extractedMappings);
log.warning(
`Updated extracted mappings in current_mappings.json file, please commit the changes if desired.`
);

View file

@ -9,6 +9,7 @@
import { readFile, writeFile } from 'fs/promises';
import Path from 'path';
import { FieldListMap } from '@kbn/core-saved-objects-base-server-internal';
import { prettyPrintAndSortKeys } from '@kbn/utils';
const CURRENT_FIELDS_FILE_PATH = Path.resolve(__dirname, '../../current_fields.json');
@ -25,5 +26,5 @@ export const readCurrentFields = async (): Promise<FieldListMap> => {
};
export const writeCurrentFields = async (fieldMap: FieldListMap) => {
await writeFile(CURRENT_FIELDS_FILE_PATH, JSON.stringify(fieldMap, null, 2) + '\n', 'utf-8');
await writeFile(CURRENT_FIELDS_FILE_PATH, prettyPrintAndSortKeys(fieldMap) + '\n', 'utf-8');
};

View file

@ -28,5 +28,6 @@
"@kbn/safer-lodash-set",
"@kbn/tooling-log",
"@kbn/core-saved-objects-server",
"@kbn/utils",
]
}

View file

@ -5,6 +5,6 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export * from './src/json';
export * from './src/path';
export * from './src/streams';

View file

@ -0,0 +1,85 @@
/*
* 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 { prettyPrintAndSortKeys } from '.';
describe('prettyPrintAndSortKeys', () => {
it('pretty prints JSON and consistently sorts the keys', () => {
const object1 = {
zap: { z: 1, b: 2 },
foo: 'foo',
bar: 'bar',
};
const object2 = {
foo: 'foo',
zap: { z: 1, b: 2 },
bar: 'bar',
};
expect(prettyPrintAndSortKeys(object1)).toMatchInlineSnapshot(`
"{
\\"bar\\": \\"bar\\",
\\"foo\\": \\"foo\\",
\\"zap\\": {
\\"b\\": 2,
\\"z\\": 1
}
}"
`);
expect(prettyPrintAndSortKeys(object1)).toEqual(prettyPrintAndSortKeys(object2));
});
it('pretty prints and sorts nested objects with arrays', () => {
const object = {
zap: {
a: {
b: 1,
a: 2,
},
},
foo: 'foo',
bar: 'bar',
baz: [
{
c: 2,
b: 1,
},
{
c: {
b: 1,
a: 2,
},
},
],
};
expect(prettyPrintAndSortKeys(object)).toMatchInlineSnapshot(`
"{
\\"bar\\": \\"bar\\",
\\"baz\\": [
{
\\"b\\": 1,
\\"c\\": 2
},
{
\\"c\\": {
\\"a\\": 2,
\\"b\\": 1
}
}
],
\\"foo\\": \\"foo\\",
\\"zap\\": {
\\"a\\": {
\\"a\\": 2,
\\"b\\": 1
}
}
}"
`);
});
});

View file

@ -0,0 +1,20 @@
/*
* 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.
*/
/**
* Given a JS object, will return a JSON.stringified result with consistently
* sorted keys.
*/
export function prettyPrintAndSortKeys(object: object): string {
const keys = new Set<string>();
JSON.stringify(object, (key, value) => {
keys.add(key);
return value;
});
return JSON.stringify(object, Array.from(keys).sort(), 2);
}