Skip to content

Commit

Permalink
[7.x] [Core] Rewrite saved objects in typescript (elastic#36829) (ela…
Browse files Browse the repository at this point in the history
…stic#38249)

* [Core] Rewrite saved objects in typescript (elastic#36829)

* Convert simple files to TS

* Fix jest tests

* Rename saved_objects_client{.js => .ts}

* WIP saved_objects_client

* saved_objects repository{.js => .ts}

* includedFields support string[] for type paramater

* Repository/saved_objects_client -> TS

* Fix tests and dependencies

* Fix saved objects type errors and simplify

* saved_objects/index saved_objects/service/index -> ts

* Fix saved objects export test after switching to typed mock

* Workaround type error

* Revert "Workaround type error"

This reverts commit de32522.

* Correctly type Server.savedObjects.SaveObjectsClient constructor

* saved_objects/service/lib/index.{js -> ts}

* saved_objects/service/lib/scoped_client_provider{js -> ts}

* Typescriptify scoped_client_provider

* Fix x-pack jest imports

* Add lodash/internal/toPath typings to xpath

* Introduce SavedObjectsClientContract

We need a way to specify that injected dependencies should adhere to the
SavedObjectsClient "contract". We can't use the SavedObjectsClient class
itself since it contains the private _repository property which in TS is
included in the type signature of a class.

* Cleanup and simplify types

* Fix repository#delete should return {}

* Add SavedObjects repository test for uncovered bug

Test for a bug in our previous js implementation that can lead to data
corruption and data loss.

If a bulkGet request is made where one of the objects to fetch is of a type
that isn't allowed, the returned result will include documents which have the
incorrect id and type assigned. E.g. the data of an object with id '1' is
returned with id '2'. Saving '2' will incorrectly override it's data with that
of the data of object '1'.

* SavedObject.updated_at: string and unify saved_object / serializer types

* Cleanup

* Address code review feedback

* Don't mock errors helpers in SavedObjectsClient Mock

* Address CR feedback

* CR Feedback #2

* Add kibana-platform as code owners of Saved Objects

* Better typings for SavedObjectsClient.errors

* Use unknown as default for generic type request paramater

* Bump @types/elasticsearch

* Fix types for isForbiddenError

* Bump x-pack @types/elasticsearch

* Update yarn.lock
  • Loading branch information
rudolf committed Jun 7, 2019
1 parent 2b5a429 commit 9756ade
Show file tree
Hide file tree
Showing 50 changed files with 919 additions and 974 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@
"@types/d3": "^3.5.41",
"@types/dedent": "^0.7.0",
"@types/delete-empty": "^2.0.0",
"@types/elasticsearch": "^5.0.30",
"@types/elasticsearch": "^5.0.33",
"@types/enzyme": "^3.1.12",
"@types/eslint": "^4.16.6",
"@types/execa": "^0.9.0",
Expand Down
2 changes: 1 addition & 1 deletion src/legacy/server/kbn_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import configCompleteMixin from './config/complete';
import optimizeMixin from '../../optimize';
import * as Plugins from './plugins';
import { indexPatternsMixin } from './index_patterns';
import { savedObjectsMixin } from './saved_objects';
import { savedObjectsMixin } from './saved_objects/saved_objects_mixin';
import { sampleDataMixin } from './sample_data';
import { capabilitiesMixin } from './capabilities';
import { urlShorteningMixin } from './url_shortening';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,10 @@
*/

import { getSortedObjectsForExport } from './get_sorted_objects_for_export';
import { SavedObjectsClientMock } from '../service/saved_objects_client.mock';

describe('getSortedObjectsForExport()', () => {
const savedObjectsClient = {
errors: {} as any,
find: jest.fn(),
bulkGet: jest.fn(),
create: jest.fn(),
bulkCreate: jest.fn(),
delete: jest.fn(),
get: jest.fn(),
update: jest.fn(),
};
const savedObjectsClient = SavedObjectsClientMock.create();

afterEach(() => {
savedObjectsClient.find.mockReset();
Expand All @@ -48,8 +40,10 @@ describe('getSortedObjectsForExport()', () => {
{
id: '2',
type: 'search',
attributes: {},
references: [
{
name: 'name',
type: 'index-pattern',
id: '1',
},
Expand All @@ -58,9 +52,12 @@ describe('getSortedObjectsForExport()', () => {
{
id: '1',
type: 'index-pattern',
attributes: {},
references: [],
},
],
per_page: 1,
page: 0,
});
const response = await getSortedObjectsForExport({
savedObjectsClient,
Expand All @@ -70,15 +67,18 @@ describe('getSortedObjectsForExport()', () => {
expect(response).toMatchInlineSnapshot(`
Array [
Object {
"attributes": Object {},
"id": "1",
"references": Array [],
"type": "index-pattern",
},
Object {
"attributes": Object {},
"id": "2",
"references": Array [
Object {
"id": "1",
"name": "name",
"type": "index-pattern",
},
],
Expand Down Expand Up @@ -118,19 +118,24 @@ Array [
{
id: '2',
type: 'search',
attributes: {},
references: [
{
type: 'index-pattern',
name: 'name',
id: '1',
},
],
},
{
id: '1',
type: 'index-pattern',
attributes: {},
references: [],
},
],
per_page: 1,
page: 0,
});
await expect(
getSortedObjectsForExport({
Expand All @@ -147,16 +152,19 @@ Array [
{
id: '2',
type: 'search',
attributes: {},
references: [
{
type: 'index-pattern',
id: '1',
name: 'name',
type: 'index-pattern',
},
],
},
{
id: '1',
type: 'index-pattern',
attributes: {},
references: [],
},
],
Expand All @@ -179,15 +187,18 @@ Array [
expect(response).toMatchInlineSnapshot(`
Array [
Object {
"attributes": Object {},
"id": "1",
"references": Array [],
"type": "index-pattern",
},
Object {
"attributes": Object {},
"id": "2",
"references": Array [
Object {
"id": "1",
"name": "name",
"type": "index-pattern",
},
],
Expand Down Expand Up @@ -227,9 +238,11 @@ Array [
{
id: '2',
type: 'search',
attributes: {},
references: [
{
type: 'index-pattern',
name: 'name',
id: '1',
},
],
Expand All @@ -241,6 +254,7 @@ Array [
{
id: '1',
type: 'index-pattern',
attributes: {},
references: [],
},
],
Expand All @@ -260,15 +274,18 @@ Array [
expect(response).toMatchInlineSnapshot(`
Array [
Object {
"attributes": Object {},
"id": "1",
"references": Array [],
"type": "index-pattern",
},
Object {
"attributes": Object {},
"id": "2",
"references": Array [
Object {
"id": "1",
"name": "name",
"type": "index-pattern",
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import Boom from 'boom';
import { SavedObjectsClient } from '../service/saved_objects_client';
import { SavedObjectsClientContract } from '../';
import { injectNestedDependencies } from './inject_nested_depdendencies';
import { sortObjects } from './sort_objects';

Expand All @@ -30,7 +30,7 @@ interface ObjectToExport {
interface ExportObjectsOptions {
types?: string[];
objects?: ObjectToExport[];
savedObjectsClient: SavedObjectsClient;
savedObjectsClient: SavedObjectsClientContract;
exportSizeLimit: number;
includeReferencesDeep?: boolean;
}
Expand All @@ -44,7 +44,7 @@ async function fetchObjectsToExport({
objects?: ObjectToExport[];
types?: string[];
exportSizeLimit: number;
savedObjectsClient: SavedObjectsClient;
savedObjectsClient: SavedObjectsClientContract;
}) {
if (objects) {
if (objects.length > exportSizeLimit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import Boom from 'boom';
import { SavedObject, SavedObjectsClient } from '../service/saved_objects_client';
import { SavedObject, SavedObjectsClientContract } from '../service/saved_objects_client';

export function getObjectReferencesToFetch(savedObjectsMap: Map<string, SavedObject>) {
const objectsToFetch = new Map<string, { type: string; id: string }>();
Expand All @@ -34,7 +34,7 @@ export function getObjectReferencesToFetch(savedObjectsMap: Map<string, SavedObj

export async function injectNestedDependencies(
savedObjects: SavedObject[],
savedObjectsClient: SavedObjectsClient
savedObjectsClient: SavedObjectsClientContract
) {
const savedObjectsMap = new Map<string, SavedObject>();
for (const savedObject of savedObjects) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@
*/

import { Readable } from 'stream';
import { SavedObjectsClient } from '../service';
import { collectSavedObjects } from './collect_saved_objects';
import { extractErrors } from './extract_errors';
import { ImportError } from './types';
import { validateReferences } from './validate_references';
import { SavedObjectsClientContract } from '../';

interface ImportSavedObjectsOptions {
readStream: Readable;
objectLimit: number;
overwrite: boolean;
savedObjectsClient: SavedObjectsClient;
savedObjectsClient: SavedObjectsClientContract;
supportedTypes: string[];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import { Readable } from 'stream';
import { SavedObjectsClient } from '../service';
import { SavedObjectsClientContract } from '../';
import { collectSavedObjects } from './collect_saved_objects';
import { createObjectsFilter } from './create_objects_filter';
import { extractErrors } from './extract_errors';
Expand All @@ -29,7 +29,7 @@ import { validateReferences } from './validate_references';
interface ResolveImportErrorsOptions {
readStream: Readable;
objectLimit: number;
savedObjectsClient: SavedObjectsClient;
savedObjectsClient: SavedObjectsClientContract;
retries: Retry[];
supportedTypes: string[];
}
Expand Down
6 changes: 3 additions & 3 deletions src/legacy/server/saved_objects/import/validate_references.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import Boom from 'boom';
import { SavedObject, SavedObjectsClient } from '../service';
import { SavedObject, SavedObjectsClientContract } from '../';
import { ImportError } from './types';

const REF_TYPES_TO_VLIDATE = ['index-pattern', 'search'];
Expand All @@ -29,7 +29,7 @@ function filterReferencesToValidate({ type }: { type: string }) {

export async function getNonExistingReferenceAsKeys(
savedObjects: SavedObject[],
savedObjectsClient: SavedObjectsClient
savedObjectsClient: SavedObjectsClientContract
) {
const collector = new Map();
// Collect all references within objects
Expand Down Expand Up @@ -77,7 +77,7 @@ export async function getNonExistingReferenceAsKeys(

export async function validateReferences(
savedObjects: SavedObject[],
savedObjectsClient: SavedObjectsClient
savedObjectsClient: SavedObjectsClientContract
) {
const errorMap: { [key: string]: ImportError } = {};
const nonExistingReferenceKeys = await getNonExistingReferenceAsKeys(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
* under the License.
*/

export { savedObjectsMixin } from './saved_objects_mixin';
export { SavedObjectsClient } from './service';
export * from './service';

export { SavedObjectsSchema } from './schema';

export { SavedObjectsManagement } from './management';
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ import Boom from 'boom';
import _ from 'lodash';
import cloneDeep from 'lodash.clonedeep';
import Semver from 'semver';
import { MigrationVersion, RawSavedObjectDoc } from '../../serialization';
import { RawSavedObjectDoc } from '../../serialization';
import { MigrationVersion } from '../../';
import { LogFn, Logger, MigrationLogger } from './migration_logger';

export type TransformFn = (doc: RawSavedObjectDoc, log?: Logger) => RawSavedObjectDoc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@

import _ from 'lodash';
import { IndexMapping } from '../../../mappings';
import { MigrationVersion } from '../../serialization';
import { MigrationVersion } from '../../';
import { AliasAction, CallCluster, NotFound, RawDoc, ShardsInfo } from './call_cluster';

// @ts-ignore untyped dependency
import { getTypes } from '../../../mappings';

const settings = { number_of_shards: 1, auto_expand_replicas: '0-1' };

export interface FullIndexInfo {
Expand Down
17 changes: 5 additions & 12 deletions src/legacy/server/saved_objects/routes/bulk_create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,14 @@
import Hapi from 'hapi';
import { createMockServer } from './_mock_server';
import { createBulkCreateRoute } from './bulk_create';
import { SavedObjectsClientMock } from '../service/saved_objects_client.mock';

describe('POST /api/saved_objects/_bulk_create', () => {
let server: Hapi.Server;
const savedObjectsClient = {
errors: {} as any,
bulkCreate: jest.fn(),
bulkGet: jest.fn(),
create: jest.fn(),
delete: jest.fn(),
find: jest.fn(),
get: jest.fn(),
update: jest.fn(),
};
const savedObjectsClient = SavedObjectsClientMock.create();

beforeEach(() => {
savedObjectsClient.bulkCreate.mockImplementation(() => Promise.resolve(''));
savedObjectsClient.bulkCreate.mockImplementation(() => Promise.resolve('' as any));
server = createMockServer();

const prereqs = {
Expand Down Expand Up @@ -75,7 +67,8 @@ describe('POST /api/saved_objects/_bulk_create', () => {
id: 'abc123',
type: 'index-pattern',
title: 'logstash-*',
version: 2,
attributes: {},
version: '2',
references: [],
},
],
Expand Down
4 changes: 2 additions & 2 deletions src/legacy/server/saved_objects/routes/bulk_create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import Hapi from 'hapi';
import Joi from 'joi';
import { SavedObjectAttributes, SavedObjectsClient } from '../';
import { SavedObjectAttributes, SavedObjectsClientContract } from '../';
import { Prerequisites, SavedObjectReference, WithoutQueryAndParams } from './types';

interface SavedObject {
Expand All @@ -33,7 +33,7 @@ interface SavedObject {

interface BulkCreateRequest extends WithoutQueryAndParams<Hapi.Request> {
pre: {
savedObjectsClient: SavedObjectsClient;
savedObjectsClient: SavedObjectsClientContract;
};
query: {
overwrite: boolean;
Expand Down
Loading

0 comments on commit 9756ade

Please sign in to comment.