[7.x] [Index Patterns] Fix return saved index pattern object (#101051) (#101134)

* [Index Patterns] Fix return saved index pattern object (#101051)

* update docs
This commit is contained in:
Anton Dosov 2021-06-02 13:38:47 +02:00 committed by GitHub
parent abaa442a0f
commit 4202cb42dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 146 additions and 167 deletions

View file

@ -8,26 +8,30 @@
```typescript
getAggregationRestrictions(): Record<string, Record<string, {
agg?: string | undefined;
agg?: string | undefined; /**
* Get last saved saved object fields
*/
interval?: number | undefined;
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined; /**
delay?: string | undefined;
time_zone?: string | undefined; /**
* Reset last saved saved object fields. used after saving
*/
time_zone?: string | undefined;
}>> | undefined;
```
<b>Returns:</b>
`Record<string, Record<string, {
agg?: string | undefined;
agg?: string | undefined; /**
* Get last saved saved object fields
*/
interval?: number | undefined;
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined; /**
delay?: string | undefined;
time_zone?: string | undefined; /**
* Reset last saved saved object fields. used after saving
*/
time_zone?: string | undefined;
}>> | undefined`

View file

@ -9,33 +9,9 @@ Returns index pattern as saved object body for saving
<b>Signature:</b>
```typescript
getAsSavedObjectBody(): {
fieldAttrs: string | undefined;
title: string;
timeFieldName: string | undefined;
intervalName: string | undefined;
sourceFilters: string | undefined;
fields: string | undefined;
fieldFormatMap: string | undefined;
type: string | undefined;
typeMeta: string | undefined;
allowNoIndex: true | undefined;
runtimeFieldMap: string | undefined;
};
getAsSavedObjectBody(): IndexPatternAttributes;
```
<b>Returns:</b>
`{
fieldAttrs: string | undefined;
title: string;
timeFieldName: string | undefined;
intervalName: string | undefined;
sourceFilters: string | undefined;
fields: string | undefined;
fieldFormatMap: string | undefined;
type: string | undefined;
typeMeta: string | undefined;
allowNoIndex: true | undefined;
runtimeFieldMap: string | undefined;
}`
`IndexPatternAttributes`

View file

@ -8,26 +8,30 @@
```typescript
getAggregationRestrictions(): Record<string, Record<string, {
agg?: string | undefined;
agg?: string | undefined; /**
* Get last saved saved object fields
*/
interval?: number | undefined;
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined; /**
delay?: string | undefined;
time_zone?: string | undefined; /**
* Reset last saved saved object fields. used after saving
*/
time_zone?: string | undefined;
}>> | undefined;
```
<b>Returns:</b>
`Record<string, Record<string, {
agg?: string | undefined;
agg?: string | undefined; /**
* Get last saved saved object fields
*/
interval?: number | undefined;
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined; /**
delay?: string | undefined;
time_zone?: string | undefined; /**
* Reset last saved saved object fields. used after saving
*/
time_zone?: string | undefined;
}>> | undefined`

View file

@ -9,33 +9,9 @@ Returns index pattern as saved object body for saving
<b>Signature:</b>
```typescript
getAsSavedObjectBody(): {
fieldAttrs: string | undefined;
title: string;
timeFieldName: string | undefined;
intervalName: string | undefined;
sourceFilters: string | undefined;
fields: string | undefined;
fieldFormatMap: string | undefined;
type: string | undefined;
typeMeta: string | undefined;
allowNoIndex: true | undefined;
runtimeFieldMap: string | undefined;
};
getAsSavedObjectBody(): IndexPatternAttributes;
```
<b>Returns:</b>
`{
fieldAttrs: string | undefined;
title: string;
timeFieldName: string | undefined;
intervalName: string | undefined;
sourceFilters: string | undefined;
fields: string | undefined;
fieldFormatMap: string | undefined;
type: string | undefined;
typeMeta: string | undefined;
allowNoIndex: true | undefined;
runtimeFieldMap: string | undefined;
}`
`IndexPatternAttributes`

View file

@ -7,7 +7,7 @@
*/
import _, { each, reject } from 'lodash';
import { FieldAttrs, FieldAttrSet } from '../..';
import { FieldAttrs, FieldAttrSet, IndexPatternAttributes } from '../..';
import type { RuntimeField } from '../types';
import { DuplicateField } from '../../../../kibana_utils/common';
@ -331,7 +331,7 @@ export class IndexPattern implements IIndexPattern {
/**
* Returns index pattern as saved object body for saving
*/
getAsSavedObjectBody() {
getAsSavedObjectBody(): IndexPatternAttributes {
const fieldFormatMap = _.isEmpty(this.fieldFormatMap)
? undefined
: JSON.stringify(this.fieldFormatMap);
@ -344,12 +344,10 @@ export class IndexPattern implements IIndexPattern {
timeFieldName: this.timeFieldName,
intervalName: this.intervalName,
sourceFilters: this.sourceFilters ? JSON.stringify(this.sourceFilters) : undefined,
fields: this.fields
? JSON.stringify(this.fields.filter((field) => field.scripted))
: undefined,
fields: JSON.stringify(this.fields?.filter((field) => field.scripted) ?? []),
fieldFormatMap,
type: this.type,
typeMeta: this.typeMeta ? JSON.stringify(this.typeMeta) : undefined,
type: this.type!,
typeMeta: JSON.stringify(this.typeMeta ?? {}),
allowNoIndex: this.allowNoIndex ? this.allowNoIndex : undefined,
runtimeFieldMap: runtimeFieldMap ? JSON.stringify(runtimeFieldMap) : undefined,
};

View file

@ -231,7 +231,12 @@ describe('IndexPatterns', () => {
test('createAndSave', async () => {
const title = 'kibana-*';
indexPatterns.createSavedObject = jest.fn();
indexPatterns.createSavedObject = jest.fn(() =>
Promise.resolve(({
id: 'id',
} as unknown) as IndexPattern)
);
indexPatterns.setDefault = jest.fn();
await indexPatterns.createAndSave({ title });
expect(indexPatterns.createSavedObject).toBeCalled();

View file

@ -407,6 +407,12 @@ export class IndexPatternsService {
throw new SavedObjectNotFound(savedObjectType, id, 'management/kibana/indexPatterns');
}
return this.initFromSavedObject(savedObject);
};
private initFromSavedObject = async (
savedObject: SavedObject<IndexPatternAttributes>
): Promise<IndexPattern> => {
const spec = this.savedObjectToSpec(savedObject);
const { title, type, typeMeta, runtimeFieldMap } = spec;
spec.fieldAttrs = savedObject.attributes.fieldAttrs
@ -416,7 +422,7 @@ export class IndexPatternsService {
try {
spec.fields = await this.refreshFieldSpecMap(
spec.fields || {},
id,
savedObject.id,
spec.title as string,
{
pattern: title as string,
@ -427,6 +433,7 @@ export class IndexPatternsService {
},
spec.fieldAttrs
);
// CREATE RUNTIME FIELDS
for (const [key, value] of Object.entries(runtimeFieldMap || {})) {
// do not create runtime field if mapped field exists
@ -454,7 +461,7 @@ export class IndexPatternsService {
this.onError(err, {
title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', {
defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})',
values: { id, title },
values: { id: savedObject.id, title },
}),
});
}
@ -548,9 +555,9 @@ export class IndexPatternsService {
async createAndSave(spec: IndexPatternSpec, override = false, skipFetchFields = false) {
const indexPattern = await this.create(spec, skipFetchFields);
await this.createSavedObject(indexPattern, override);
await this.setDefault(indexPattern.id!);
return indexPattern;
const createdIndexPattern = await this.createSavedObject(indexPattern, override);
await this.setDefault(createdIndexPattern.id!);
return createdIndexPattern;
}
/**
@ -570,15 +577,20 @@ export class IndexPatternsService {
}
const body = indexPattern.getAsSavedObjectBody();
const response = await this.savedObjectsClient.create(savedObjectType, body, {
id: indexPattern.id,
});
indexPattern.id = response.id;
this.indexPatternCache.set(indexPattern.id, Promise.resolve(indexPattern));
const response: SavedObject<IndexPatternAttributes> = (await this.savedObjectsClient.create(
savedObjectType,
body,
{
id: indexPattern.id,
}
)) as SavedObject<IndexPatternAttributes>;
const createdIndexPattern = await this.initFromSavedObject(response);
this.indexPatternCache.set(createdIndexPattern.id!, Promise.resolve(createdIndexPattern));
if (this.savedObjectsCache) {
this.savedObjectsCache.push(response as SavedObject<IndexPatternSavedObjectAttrs>);
}
return indexPattern;
return createdIndexPattern;
}
/**

View file

@ -1330,28 +1330,18 @@ export class IndexPattern implements IIndexPattern {
};
// (undocumented)
getAggregationRestrictions(): Record<string, Record<string, {
agg?: string | undefined;
agg?: string | undefined; /**
* Get last saved saved object fields
*/
interval?: number | undefined;
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined; /**
delay?: string | undefined;
time_zone?: string | undefined; /**
* Reset last saved saved object fields. used after saving
*/
time_zone?: string | undefined;
}>> | undefined;
getAsSavedObjectBody(): {
fieldAttrs: string | undefined;
title: string;
timeFieldName: string | undefined;
intervalName: string | undefined;
sourceFilters: string | undefined;
fields: string | undefined;
fieldFormatMap: string | undefined;
type: string | undefined;
typeMeta: string | undefined;
allowNoIndex: true | undefined;
runtimeFieldMap: string | undefined;
};
getAsSavedObjectBody(): IndexPatternAttributes;
// (undocumented)
getComputedFields(): {
storedFields: string[];

View file

@ -15,9 +15,8 @@ import type { DataPluginStart, DataPluginStartDependencies } from '../../plugin'
const indexPatternSpecSchema = schema.object({
title: schema.string(),
id: schema.maybe(schema.string()),
version: schema.maybe(schema.string()),
id: schema.maybe(schema.string()),
type: schema.maybe(schema.string()),
timeFieldName: schema.maybe(schema.string()),
sourceFilters: schema.maybe(

View file

@ -772,28 +772,18 @@ export class IndexPattern implements IIndexPattern {
};
// (undocumented)
getAggregationRestrictions(): Record<string, Record<string, {
agg?: string | undefined;
agg?: string | undefined; /**
* Get last saved saved object fields
*/
interval?: number | undefined;
fixed_interval?: string | undefined;
calendar_interval?: string | undefined;
delay?: string | undefined; /**
delay?: string | undefined;
time_zone?: string | undefined; /**
* Reset last saved saved object fields. used after saving
*/
time_zone?: string | undefined;
}>> | undefined;
getAsSavedObjectBody(): {
fieldAttrs: string | undefined;
title: string;
timeFieldName: string | undefined;
intervalName: string | undefined;
sourceFilters: string | undefined;
fields: string | undefined;
fieldFormatMap: string | undefined;
type: string | undefined;
typeMeta: string | undefined;
allowNoIndex: true | undefined;
runtimeFieldMap: string | undefined;
};
getAsSavedObjectBody(): IndexPatternAttributes;
// (undocumented)
getComputedFields(): {
storedFields: string[];

View file

@ -11,6 +11,7 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
describe('main', () => {
it('can create an index_pattern with just a title', async () => {
@ -45,7 +46,6 @@ export default function ({ getService }: FtrProviderContext) {
index_pattern: {
title,
id,
version: 'test-version',
type: 'test-type',
timeFieldName: 'test-timeFieldName',
},
@ -54,7 +54,6 @@ export default function ({ getService }: FtrProviderContext) {
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
expect(response.body.index_pattern.id).to.be(id);
expect(response.body.index_pattern.version).to.be('test-version');
expect(response.body.index_pattern.type).to.be('test-type');
expect(response.body.index_pattern.timeFieldName).to.be('test-timeFieldName');
});
@ -77,60 +76,85 @@ export default function ({ getService }: FtrProviderContext) {
expect(response.body.index_pattern.sourceFilters[0].value).to.be('foo');
});
it('can specify optional fields attribute when creating an index pattern', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
},
},
},
describe('creating fields', () => {
before(async () => {
await esArchiver.load('index_patterns/basic_index');
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
expect(response.body.index_pattern.fields.foo.name).to.be('foo');
expect(response.body.index_pattern.fields.foo.type).to.be('string');
});
it('can add two fields, one with all fields specified', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
index_pattern: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
},
bar: {
name: 'bar',
type: 'number',
count: 123,
script: '',
esTypes: ['test-type'],
scripted: true,
},
},
},
after(async () => {
await esArchiver.unload('index_patterns/basic_index');
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
it('can specify optional fields attribute when creating an index pattern', async () => {
const title = `basic_index*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
scripted: true,
script: "doc['field_name'].value",
},
},
},
});
expect(response.body.index_pattern.fields.foo.name).to.be('foo');
expect(response.body.index_pattern.fields.foo.type).to.be('string');
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
expect(response.body.index_pattern.fields.foo.name).to.be('foo');
expect(response.body.index_pattern.fields.foo.type).to.be('string');
expect(response.body.index_pattern.fields.foo.scripted).to.be(true);
expect(response.body.index_pattern.fields.foo.script).to.be("doc['field_name'].value");
expect(response.body.index_pattern.fields.bar.name).to.be('bar');
expect(response.body.index_pattern.fields.bar.type).to.be('number');
expect(response.body.index_pattern.fields.bar.count).to.be(123);
expect(response.body.index_pattern.fields.bar.script).to.be('');
expect(response.body.index_pattern.fields.bar.esTypes[0]).to.be('test-type');
expect(response.body.index_pattern.fields.bar.scripted).to.be(true);
expect(response.body.index_pattern.fields.bar.name).to.be('bar'); // created from es index
expect(response.body.index_pattern.fields.bar.type).to.be('boolean');
});
it('Can add scripted fields, other fields created from es index', async () => {
const title = `basic_index*`;
const response = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
fields: {
foo: {
name: 'foo',
type: 'string',
},
fake: {
name: 'fake',
type: 'string',
},
bar: {
name: 'bar',
type: 'number',
count: 123,
script: '',
esTypes: ['test-type'],
scripted: true,
},
},
},
});
expect(response.status).to.be(200);
expect(response.body.index_pattern.title).to.be(title);
expect(response.body.index_pattern.fields.foo.name).to.be('foo');
expect(response.body.index_pattern.fields.foo.type).to.be('number'); // picked up from index
expect(response.body.index_pattern.fields.fake).to.be(undefined); // not in index, so not created
expect(response.body.index_pattern.fields.bar.name).to.be('bar');
expect(response.body.index_pattern.fields.bar.type).to.be('number');
expect(response.body.index_pattern.fields.bar.count).to.be(123);
expect(response.body.index_pattern.fields.bar.script).to.be('');
expect(response.body.index_pattern.fields.bar.esTypes[0]).to.be('test-type');
expect(response.body.index_pattern.fields.bar.scripted).to.be(true);
});
});
it('can specify optional typeMeta attribute when creating an index pattern', async () => {

View file

@ -25,6 +25,7 @@ export default function ({ getService }: FtrProviderContext) {
it('can create a new scripted field', async () => {
const title = `foo-${Date.now()}-${Math.random()}*`;
const response1 = await supertest.post('/api/index_patterns/index_pattern').send({
override: true,
index_pattern: {
title,
},