Beginning to update index pattern api resource schema
This commit is contained in:
parent
6f0dcefc69
commit
66b3c1eb97
7 changed files with 168 additions and 100 deletions
|
@ -0,0 +1,12 @@
|
|||
const Joi = require('joi');
|
||||
|
||||
module.exports = function (primary, included) {
|
||||
const doc = {data: primary};
|
||||
if (included) {
|
||||
doc.included = included;
|
||||
}
|
||||
|
||||
return Joi.object(doc);
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
const Joi = require('joi');
|
||||
|
||||
module.exports = function (attributes, relationships) {
|
||||
const resource = {
|
||||
type: Joi.string().required(),
|
||||
id: Joi.string().required(),
|
||||
attributes: attributes
|
||||
};
|
||||
if (relationships) {
|
||||
resource.relationships = relationships;
|
||||
}
|
||||
|
||||
return Joi.object(resource);
|
||||
};
|
||||
|
|
@ -1,31 +1,60 @@
|
|||
var Joi = require('joi');
|
||||
const Joi = require('joi');
|
||||
const createApiDocumentSchema = require('./create_api_document_schema');
|
||||
const createResourceObject = require('./create_resource_object');
|
||||
const relationshipObjectSchema = require('./relationship_object_schema');
|
||||
|
||||
|
||||
module.exports = {
|
||||
post: Joi.object({
|
||||
post: createApiDocumentSchema(
|
||||
createResourceObject(
|
||||
Joi.object({
|
||||
title: Joi.string().required(),
|
||||
time_field_name: Joi.string(),
|
||||
interval_name: Joi.string(),
|
||||
fields: Joi.array().items(Joi.object({
|
||||
fields: Joi.array().items(
|
||||
Joi.object({
|
||||
name: Joi.string().required(),
|
||||
count: Joi.number().integer(),
|
||||
scripted: Joi.boolean(),
|
||||
mapping: Joi.object({
|
||||
type: Joi.string().required()
|
||||
}).unknown()
|
||||
})),
|
||||
scripted: Joi.boolean()
|
||||
})
|
||||
),
|
||||
field_format_map: Joi.object()
|
||||
}),
|
||||
Joi.object({
|
||||
template: relationshipObjectSchema
|
||||
})
|
||||
),
|
||||
Joi.array().items(
|
||||
createResourceObject(
|
||||
Joi.object({
|
||||
template: Joi.string().required(),
|
||||
order: Joi.number().integer(),
|
||||
mappings: Joi.object()
|
||||
})
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
put: Joi.object({
|
||||
// No attributes are required for an update
|
||||
// Templates can't be updated in an index_pattern PUT
|
||||
put: createApiDocumentSchema(
|
||||
createResourceObject(
|
||||
Joi.object({
|
||||
title: Joi.string(),
|
||||
time_field_name: Joi.string(),
|
||||
interval_name: Joi.string(),
|
||||
fields: Joi.array().items(Joi.object({
|
||||
fields: Joi.array().items(
|
||||
Joi.object({
|
||||
name: Joi.string().required(),
|
||||
count: Joi.number().integer(),
|
||||
scripted: Joi.boolean(),
|
||||
mapping: Joi.any().forbidden()
|
||||
})),
|
||||
field_format_map: Joi.object()
|
||||
scripted: Joi.boolean()
|
||||
})
|
||||
),
|
||||
field_format_map: Joi.object()
|
||||
}),
|
||||
Joi.object({
|
||||
template: relationshipObjectSchema
|
||||
})
|
||||
)
|
||||
)
|
||||
};
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
const Joi = require('joi');
|
||||
|
||||
module.exports = Joi.object({
|
||||
data: Joi.object({
|
||||
type: Joi.string().required(),
|
||||
id: Joi.string().required()
|
||||
})
|
||||
});
|
||||
|
|
@ -19,17 +19,14 @@ module.exports = function registerPost(server) {
|
|||
}
|
||||
|
||||
const callWithRequest = server.plugins.elasticsearch.callWithRequest;
|
||||
const indexPattern = _.cloneDeep(req.payload);
|
||||
const requestDocument = _.cloneDeep(req.payload);
|
||||
const included = requestDocument.included;
|
||||
const indexPatternId = requestDocument.data.id;
|
||||
const indexPattern = requestDocument.data.attributes;
|
||||
const isWildcard = _.contains(indexPattern.title, '*');
|
||||
const mappings = _(req.payload.fields)
|
||||
.indexBy('name')
|
||||
.mapValues(value => value.mapping)
|
||||
.omit(_.isUndefined)
|
||||
.value();
|
||||
const templateResource = _.isEmpty(included) ? null : included[0];
|
||||
|
||||
indexPattern.fields = JSON.stringify(_.map(indexPattern.fields, (field) => {
|
||||
return _.omit(field, 'mapping');
|
||||
}));
|
||||
indexPattern.fields = JSON.stringify(indexPattern.fields);
|
||||
|
||||
const patternCreateParams = {
|
||||
index: '.kibana',
|
||||
|
@ -40,7 +37,7 @@ module.exports = function registerPost(server) {
|
|||
|
||||
callWithRequest(req, 'create', patternCreateParams)
|
||||
.then((patternResponse) => {
|
||||
if (!isWildcard || _.isEmpty(mappings)) {
|
||||
if (!isWildcard || _.isEmpty(included)) {
|
||||
return patternResponse;
|
||||
}
|
||||
|
||||
|
@ -51,17 +48,10 @@ module.exports = function registerPost(server) {
|
|||
}
|
||||
|
||||
const templateParams = {
|
||||
order: 0,
|
||||
order: templateResource.attributes.order,
|
||||
create: true,
|
||||
name: patternToTemplate(indexPattern.title),
|
||||
body: {
|
||||
template: indexPattern.title,
|
||||
mappings: {
|
||||
_default_: {
|
||||
properties: mappings
|
||||
}
|
||||
}
|
||||
}
|
||||
name: templateResource.id,
|
||||
body: _.omit(templateResource.attributes, 'order')
|
||||
};
|
||||
|
||||
return callWithRequest(req, 'indices.putTemplate', templateParams);
|
||||
|
|
|
@ -24,41 +24,29 @@ define(function (require) {
|
|||
.expect(400),
|
||||
|
||||
request.post('/kibana/index_patterns')
|
||||
.send(_.assign(createTestData().indexPatternWithMappings, {title: false}))
|
||||
.send(_.set(createTestData().indexPatternWithTemplate, 'data.attributes.title', false))
|
||||
.expect(400),
|
||||
|
||||
request.post('/kibana/index_patterns')
|
||||
.send(_.assign(createTestData().indexPatternWithMappings, {fields: {}}))
|
||||
.send(_.set(createTestData().indexPatternWithTemplate, 'data.attributes.fields', {}))
|
||||
.expect(400),
|
||||
|
||||
// Fields must have a name
|
||||
request.post('/kibana/index_patterns')
|
||||
.send(_.assign(createTestData().indexPatternWithMappings, {fields: [{count: 0}]}))
|
||||
.expect(400),
|
||||
|
||||
// Mapping requires type
|
||||
request.post('/kibana/index_patterns')
|
||||
.send(_.assign(createTestData().indexPatternWithMappings, {
|
||||
fields: [{
|
||||
'name': 'geo.coordinates',
|
||||
'count': 0,
|
||||
'scripted': false,
|
||||
'mapping': {'index': 'not_analyzed', 'doc_values': false}
|
||||
}]
|
||||
}))
|
||||
.send(_.set(createTestData().indexPatternWithTemplate, 'data.attributes.fields', [{count: 0}]))
|
||||
.expect(400)
|
||||
]);
|
||||
});
|
||||
|
||||
bdd.it('should return 201 when a pattern is successfully created', function createPattern() {
|
||||
return request.post('/kibana/index_patterns')
|
||||
.send(createTestData().indexPatternWithMappings)
|
||||
.send(createTestData().indexPatternWithTemplate)
|
||||
.expect(201);
|
||||
});
|
||||
|
||||
bdd.it('should create an index template if mappings are provided', function createTemplate() {
|
||||
return request.post('/kibana/index_patterns')
|
||||
.send(createTestData().indexPatternWithMappings)
|
||||
.send(createTestData().indexPatternWithTemplate)
|
||||
.expect(201)
|
||||
.then(function () {
|
||||
return scenarioManager.client.indices.getTemplate({name: 'kibana-logstash-*'});
|
||||
|
@ -66,7 +54,7 @@ define(function (require) {
|
|||
});
|
||||
|
||||
bdd.it('should NOT create an index template if mappings are NOT provided', function noMappings() {
|
||||
var pattern = createTestData().indexPatternWithMappings;
|
||||
var pattern = createTestData().indexPatternWithTemplate;
|
||||
pattern.fields = _.map(pattern.fields, function (field) {
|
||||
return _.omit(field, 'mapping');
|
||||
});
|
||||
|
@ -85,7 +73,7 @@ define(function (require) {
|
|||
});
|
||||
|
||||
bdd.it('should NOT create an index template if pattern does not contain a wildcard', function noWildcard() {
|
||||
var pattern = createTestData().indexPatternWithMappings;
|
||||
var pattern = createTestData().indexPatternWithTemplate;
|
||||
pattern.title = 'notawildcard';
|
||||
|
||||
return request.post('/kibana/index_patterns')
|
||||
|
@ -103,11 +91,11 @@ define(function (require) {
|
|||
|
||||
bdd.it('should return 409 conflict when a pattern with the given ID already exists', function patternConflict() {
|
||||
return request.post('/kibana/index_patterns')
|
||||
.send(createTestData().indexPatternWithMappings)
|
||||
.send(createTestData().indexPatternWithTemplate)
|
||||
.expect(201)
|
||||
.then(function () {
|
||||
return request.post('/kibana/index_patterns')
|
||||
.send(createTestData().indexPatternWithMappings)
|
||||
.send(createTestData().indexPatternWithTemplate)
|
||||
.expect(409);
|
||||
});
|
||||
});
|
||||
|
@ -120,14 +108,14 @@ define(function (require) {
|
|||
}
|
||||
}).then(function () {
|
||||
return request.post('/kibana/index_patterns')
|
||||
.send(createTestData().indexPatternWithMappings)
|
||||
.send(createTestData().indexPatternWithTemplate)
|
||||
.expect(409);
|
||||
});
|
||||
});
|
||||
|
||||
bdd.it('should return 409 conflict when mappings are provided with a pattern that matches existing indices',
|
||||
function existingIndicesConflict() {
|
||||
var pattern = createTestData().indexPatternWithMappings;
|
||||
var pattern = createTestData().indexPatternWithTemplate;
|
||||
pattern.title = '.kib*';
|
||||
|
||||
return request.post('/kibana/index_patterns')
|
||||
|
@ -137,7 +125,7 @@ define(function (require) {
|
|||
|
||||
bdd.it('should return 201 created successfully if a pattern matches existing indices but has NO mappings',
|
||||
function existingIndicesNoMappings() {
|
||||
var pattern = createTestData().indexPatternWithMappings;
|
||||
var pattern = createTestData().indexPatternWithTemplate;
|
||||
pattern.fields = _.map(pattern.fields, function (field) {
|
||||
return _.omit(field, 'mapping');
|
||||
});
|
||||
|
@ -150,7 +138,7 @@ define(function (require) {
|
|||
|
||||
bdd.it('should enforce snake_case in the request body', function () {
|
||||
return request.post('/kibana/index_patterns')
|
||||
.send(_.mapKeys(createTestData().indexPatternWithMappings, function (value, key) {
|
||||
.send(_.mapKeys(createTestData().indexPatternWithTemplate, function (value, key) {
|
||||
return _.camelCase(key);
|
||||
}))
|
||||
.expect(400);
|
||||
|
|
|
@ -1,33 +1,58 @@
|
|||
module.exports = function createTestData() {
|
||||
return {
|
||||
indexPatternWithMappings: {
|
||||
indexPatternWithTemplate: {
|
||||
'data': {
|
||||
'type': 'index_patterns',
|
||||
'id': 'logstash-*',
|
||||
'attributes': {
|
||||
'title': 'logstash-*',
|
||||
'time_field_name': '@timestamp',
|
||||
'fields': [{
|
||||
'name': 'geo.coordinates',
|
||||
'count': 0,
|
||||
'scripted': false,
|
||||
'mapping': {'type': 'geo_point', 'index': 'not_analyzed', 'doc_values': false}
|
||||
'scripted': false
|
||||
}, {
|
||||
'name': 'ip',
|
||||
'count': 2,
|
||||
'scripted': false,
|
||||
'mapping': {'type': 'ip', 'index': 'not_analyzed', 'doc_values': true}
|
||||
'scripted': false
|
||||
}, {
|
||||
'name': '@timestamp',
|
||||
'count': 0,
|
||||
'scripted': false,
|
||||
'mapping': {'type': 'date', 'index': 'not_analyzed', 'doc_values': true}
|
||||
'scripted': false
|
||||
}, {
|
||||
'name': 'agent',
|
||||
'count': 0,
|
||||
'scripted': false,
|
||||
'mapping': {'type': 'string', 'index': 'analyzed', 'doc_values': false}
|
||||
'scripted': false
|
||||
}, {
|
||||
'name': 'bytes',
|
||||
'count': 2,
|
||||
'scripted': false,
|
||||
'scripted': false
|
||||
}]
|
||||
},
|
||||
'relationships': {
|
||||
'template': {
|
||||
'data': {'type': 'index_templates', 'id': 'kibana-logstash-*'}
|
||||
}
|
||||
}
|
||||
},
|
||||
'included': [{
|
||||
'type': 'index_templates',
|
||||
'id': 'kibana-logstash-*',
|
||||
'attributes': {
|
||||
'template': 'logstash-*',
|
||||
'order': 0,
|
||||
'mappings': {
|
||||
'_default_': {
|
||||
'properties': {
|
||||
'geo.coordinates': {'type': 'geo_point', 'index': 'not_analyzed', 'doc_values': false},
|
||||
'ip': {'type': 'ip', 'index': 'not_analyzed', 'doc_values': true},
|
||||
'@timestamp': {'type': 'date', 'index': 'not_analyzed', 'doc_values': true},
|
||||
'agent': {'type': 'string', 'index': 'analyzed', 'doc_values': false},
|
||||
'mapping': {'type': 'number', 'index': 'not_analyzed', 'doc_values': true}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue