From 4ce3320ab1bff785a3105d9f286b76d33b5ea466 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 26 May 2020 09:47:49 -0400 Subject: [PATCH] [Ingest pipelines] Fix schema validation for simulate and update routes (#67199) Co-authored-by: Elastic Machine --- .../server/routes/api/create.ts | 6 +- .../server/routes/api/pipeline_schema.ts | 14 ++++ .../server/routes/api/simulate.ts | 8 +- .../server/routes/api/update.ts | 8 +- .../ingest_pipelines/ingest_pipelines.ts | 73 +++++++++++++++++++ 5 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 x-pack/plugins/ingest_pipelines/server/routes/api/pipeline_schema.ts diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/create.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/create.ts index 803d34bf0042b2..d2be8c0e3e0cf8 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/create.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/create.ts @@ -9,13 +9,11 @@ import { schema } from '@kbn/config-schema'; import { Pipeline } from '../../../common/types'; import { API_BASE_PATH } from '../../../common/constants'; import { RouteDependencies } from '../../types'; +import { pipelineSchema } from './pipeline_schema'; const bodySchema = schema.object({ name: schema.string(), - description: schema.maybe(schema.string()), - processors: schema.arrayOf(schema.recordOf(schema.string(), schema.any())), - version: schema.maybe(schema.number()), - on_failure: schema.maybe(schema.arrayOf(schema.recordOf(schema.string(), schema.any()))), + ...pipelineSchema, }); export const registerCreateRoute = ({ diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/pipeline_schema.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/pipeline_schema.ts new file mode 100644 index 00000000000000..408c0e9933a7c3 --- /dev/null +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/pipeline_schema.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; + +export const pipelineSchema = { + description: schema.maybe(schema.string()), + processors: schema.arrayOf(schema.recordOf(schema.string(), schema.any())), + version: schema.maybe(schema.number()), + on_failure: schema.maybe(schema.arrayOf(schema.recordOf(schema.string(), schema.any()))), +}; diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/simulate.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/simulate.ts index ca5fc78d118fdd..0b7e5d886a9366 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/simulate.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/simulate.ts @@ -7,14 +7,10 @@ import { schema } from '@kbn/config-schema'; import { API_BASE_PATH } from '../../../common/constants'; import { RouteDependencies } from '../../types'; +import { pipelineSchema } from './pipeline_schema'; const bodySchema = schema.object({ - pipeline: schema.object({ - description: schema.string(), - processors: schema.arrayOf(schema.recordOf(schema.string(), schema.any())), - version: schema.maybe(schema.number()), - on_failure: schema.maybe(schema.arrayOf(schema.recordOf(schema.string(), schema.any()))), - }), + pipeline: schema.object(pipelineSchema), documents: schema.arrayOf(schema.recordOf(schema.string(), schema.any())), verbose: schema.maybe(schema.boolean()), }); diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/update.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/update.ts index a6fdee47f0ecff..3bf2b0b15a50ad 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/update.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/update.ts @@ -7,13 +7,9 @@ import { schema } from '@kbn/config-schema'; import { API_BASE_PATH } from '../../../common/constants'; import { RouteDependencies } from '../../types'; +import { pipelineSchema } from './pipeline_schema'; -const bodySchema = schema.object({ - description: schema.string(), - processors: schema.arrayOf(schema.recordOf(schema.string(), schema.any())), - version: schema.maybe(schema.number()), - on_failure: schema.maybe(schema.arrayOf(schema.recordOf(schema.string(), schema.any()))), -}); +const bodySchema = schema.object(pipelineSchema); const paramsSchema = schema.object({ name: schema.string(), diff --git a/x-pack/test/api_integration/apis/management/ingest_pipelines/ingest_pipelines.ts b/x-pack/test/api_integration/apis/management/ingest_pipelines/ingest_pipelines.ts index f82c392942d664..a48460d7a3b232 100644 --- a/x-pack/test/api_integration/apis/management/ingest_pipelines/ingest_pipelines.ts +++ b/x-pack/test/api_integration/apis/management/ingest_pipelines/ingest_pipelines.ts @@ -117,6 +117,14 @@ export default function ({ getService }: FtrProviderContext) { }, ], version: 1, + on_failure: [ + { + set: { + field: '_index', + value: 'failed-{{ _index }}', + }, + }, + ], }; before(() => createPipeline({ body: PIPELINE, id: PIPELINE_ID })); @@ -139,6 +147,23 @@ export default function ({ getService }: FtrProviderContext) { }); }); + it('should allow optional fields to be removed', async () => { + const uri = `${API_BASE_PATH}/${PIPELINE_ID}`; + + const { body } = await supertest + .put(uri) + .set('kbn-xsrf', 'xxx') + .send({ + processors: PIPELINE.processors, + // removes description, version and on_failure + }) + .expect(200); + + expect(body).to.eql({ + acknowledged: true, + }); + }); + it('should not allow a non-existing pipeline to be updated', async () => { const uri = `${API_BASE_PATH}/pipeline_does_not_exist`; @@ -313,6 +338,54 @@ export default function ({ getService }: FtrProviderContext) { }, }, ], + version: 1, + on_failure: [ + { + set: { + field: '_index', + value: 'failed-{{ _index }}', + }, + }, + ], + }, + documents: [ + { + _index: 'index', + _id: 'id', + _source: { + foo: 'bar', + }, + }, + { + _index: 'index', + _id: 'id', + _source: { + foo: 'rab', + }, + }, + ], + }) + .expect(200); + + // The simulate ES response is quite long and includes timestamps + // so for now, we just confirm the docs array is returned with the correct length + expect(body.docs?.length).to.eql(2); + }); + + it('should successfully simulate a pipeline with only required pipeline fields', async () => { + const { body } = await supertest + .post(`${API_BASE_PATH}/simulate`) + .set('kbn-xsrf', 'xxx') + .send({ + pipeline: { + processors: [ + { + set: { + field: 'field2', + value: '_value', + }, + }, + ], }, documents: [ {