From fef8485f367785b78426430a08b4b0ddd1eb1ae8 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Mon, 6 Jan 2020 16:20:45 -0700 Subject: [PATCH] [Reporting/Legacy] Remove reporting legacy job params compatibility shim (#52539) * [Reporting/Tests] consolidate functional test configs * remove console.log * trash * Update * add more to the comment * restore historic archive for wip ui functional tests * [Reporting/Legacy] Remove reporting legacy job params compatibility shimmy shim shim * objectType: objectType * fix jest test and get_urls logging * simplify change Co-authored-by: Elastic Machine --- .../common/execute_job/get_full_urls.test.ts | 36 +-- .../common/execute_job/get_full_urls.ts | 6 +- .../server/create_job/compatibility_shim.js | 126 -------- .../create_job/compatibility_shim.test.js | 297 ------------------ .../printable_pdf/server/create_job/index.ts | 32 +- .../server/execute_job/index.test.js | 9 +- .../export_types/printable_pdf/types.d.ts | 6 +- .../public/components/report_listing.tsx | 2 +- .../lib/esqueue/helpers/create_index.js | 2 +- .../reporting/server/lib/esqueue/job.js | 2 +- .../reporting/server/routes/generation.ts | 2 - .../plugins/reporting/server/routes/legacy.ts | 73 ----- x-pack/test/reporting/README.md | 10 - .../reporting/api/bwc_existing_indexes.js | 78 ----- .../test/reporting/api/bwc_generation_urls.js | 54 ---- x-pack/test/reporting/api/chromium_tests.js | 2 - x-pack/test/reporting/api/generation_urls.js | 14 - 17 files changed, 38 insertions(+), 713 deletions(-) delete mode 100644 x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/compatibility_shim.js delete mode 100644 x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/compatibility_shim.test.js delete mode 100644 x-pack/legacy/plugins/reporting/server/routes/legacy.ts delete mode 100644 x-pack/test/reporting/api/bwc_existing_indexes.js delete mode 100644 x-pack/test/reporting/api/bwc_generation_urls.js diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.test.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.test.ts index e25b94e98d020f..9b2a065427f70b 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.test.ts @@ -28,7 +28,7 @@ test(`fails if no URL is passed`, async () => { server: mockServer, } as FullUrlsOpts); expect(fn).toThrowErrorMatchingInlineSnapshot( - `"No valid URL fields found in Job Params! Expected \`job.relativeUrl\` or \`job.objects[{ relativeUrl }]\`"` + `"No valid URL fields found in Job Params! Expected \`job.relativeUrl: string\` or \`job.relativeUrls: string[]\`"` ); }); @@ -64,7 +64,10 @@ test(`fails if URLs are file-protocols for PDF`, async () => { const relativeUrl = 'file://etc/passwd/#/something'; const fn = () => getFullUrls({ - job: { objects: [{ relativeUrl }], forceNow }, + job: { + relativeUrls: [relativeUrl], + forceNow, + }, server: mockServer, } as FullUrlsOpts); expect(fn).toThrowErrorMatchingInlineSnapshot( @@ -79,11 +82,7 @@ test(`fails if URLs are absolute for PDF`, async () => { const fn = () => getFullUrls({ job: { - objects: [ - { - relativeUrl, - }, - ], + relativeUrls: [relativeUrl], forceNow, }, server: mockServer, @@ -95,18 +94,15 @@ test(`fails if URLs are absolute for PDF`, async () => { test(`fails if any URLs are absolute or file's for PDF`, async () => { const forceNow = '2000-01-01T00:00:00.000Z'; - const objects = [ - { relativeUrl: '/app/kibana#/something_aaa' }, - { - relativeUrl: - 'http://169.254.169.254/latest/meta-data/iam/security-credentials/profileName/#/something', - }, - { relativeUrl: 'file://etc/passwd/#/something' }, + const relativeUrls = [ + '/app/kibana#/something_aaa', + 'http://169.254.169.254/latest/meta-data/iam/security-credentials/profileName/#/something', + 'file://etc/passwd/#/something', ]; const fn = () => getFullUrls({ - job: { objects, forceNow }, + job: { relativeUrls, forceNow }, server: mockServer, } as FullUrlsOpts); expect(fn).toThrowErrorMatchingInlineSnapshot( @@ -163,11 +159,11 @@ test(`adds forceNow to each of multiple urls`, async () => { const forceNow = '2000-01-01T00:00:00.000Z'; const urls = await getFullUrls({ job: { - objects: [ - { relativeUrl: '/app/kibana#/something_aaa' }, - { relativeUrl: '/app/kibana#/something_bbb' }, - { relativeUrl: '/app/kibana#/something_ccc' }, - { relativeUrl: '/app/kibana#/something_ddd' }, + relativeUrls: [ + '/app/kibana#/something_aaa', + '/app/kibana#/something_bbb', + '/app/kibana#/something_ccc', + '/app/kibana#/something_ddd', ], forceNow, }, diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts index 90049e8e3aea48..ca64d8632dbfeb 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts @@ -20,7 +20,7 @@ function isPngJob(job: JobDocPayloadPNG | JobDocPayloadPDF): job is JobDocPayloa return (job as JobDocPayloadPNG).relativeUrl !== undefined; } function isPdfJob(job: JobDocPayloadPNG | JobDocPayloadPDF): job is JobDocPayloadPDF { - return (job as JobDocPayloadPDF).objects !== undefined; + return (job as JobDocPayloadPDF).relativeUrls !== undefined; } export function getFullUrls({ @@ -45,10 +45,10 @@ export function getFullUrls({ if (isPngJob(job)) { relativeUrls = [job.relativeUrl]; } else if (isPdfJob(job)) { - relativeUrls = job.objects.map(obj => obj.relativeUrl); + relativeUrls = job.relativeUrls; } else { throw new Error( - `No valid URL fields found in Job Params! Expected \`job.relativeUrl\` or \`job.objects[{ relativeUrl }]\`` + `No valid URL fields found in Job Params! Expected \`job.relativeUrl: string\` or \`job.relativeUrls: string[]\`` ); } diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/compatibility_shim.js b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/compatibility_shim.js deleted file mode 100644 index a3afd070603b0f..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/compatibility_shim.js +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 { uriEncode } from '../lib/uri_encode'; - -/* - * TODO: Kibana 8.0: - * Remove support for parsing Saved Object details from objectType / savedObjectId - * Including support for determining the Report title from objectType / savedObjectId - * - * - `objectType` is optional, but helps differentiate the type of report in the job listing - * - `title` must be explicitly passed - * - `relativeUrls` array OR `relativeUrl` string must be passed - */ - -const getSavedObjectTitle = async (objectType, savedObjectId, savedObjectsClient) => { - const savedObject = await savedObjectsClient.get(objectType, savedObjectId); - return savedObject.attributes.title; -}; - -const getSavedObjectRelativeUrl = (objectType, savedObjectId, queryString) => { - const appPrefixes = { - dashboard: '/dashboard/', - visualization: '/visualize/edit/', - search: '/discover/', - }; - - const appPrefix = appPrefixes[objectType]; - if (!appPrefix) throw new Error('Unexpected app type: ' + objectType); - - const hash = appPrefix + uriEncode.string(savedObjectId, true); - - return `/app/kibana#${hash}?${queryString || ''}`; -}; - -export function compatibilityShimFactory(server, logger) { - return function compatibilityShimFactory(createJobFn) { - return async function( - { - savedObjectId, // deprecating - queryString, // deprecating - browserTimezone, - objectType, - title, - relativeUrls, - layout, - }, - headers, - request - ) { - // input validation and deprecation logging - if (savedObjectId) { - if (typeof savedObjectId !== 'string') { - throw new Error('Invalid savedObjectId (deprecated). String is expected.'); - } - if (relativeUrls) { - throw new Error(`savedObjectId should not be provided if relativeUrls are provided`); - } - } else { - if (!relativeUrls) { - throw new Error(`Either relativeUrls or savedObjectId must be provided`); - } - if (!Array.isArray(relativeUrls)) { - throw new Error('Invalid relativeUrls. String[] is expected.'); - } - relativeUrls.forEach(url => { - if (typeof url !== 'string') { - throw new Error('Invalid Relative URL in relativeUrls. String is expected.'); - } - }); - } - - let kibanaRelativeUrls; - if (relativeUrls) { - kibanaRelativeUrls = relativeUrls; - } else { - kibanaRelativeUrls = [getSavedObjectRelativeUrl(objectType, savedObjectId, queryString)]; - logger.warning( - `The relativeUrls have been derived from saved object parameters. ` + - `This functionality will be removed with the next major version.` - ); - } - - let reportTitle; - try { - if (title) { - reportTitle = title; - } else { - if (objectType && savedObjectId) { - reportTitle = await getSavedObjectTitle( - objectType, - savedObjectId, - request.getSavedObjectsClient() - ); - logger.warning( - `The title has been derived from saved object parameters. This ` + - `functionality will be removed with the next major version.` - ); - } else { - logger.warning( - `A title parameter should be provided with the job generation ` + - `request. Please use Kibana to regenerate your POST URL to have a ` + - `title included in the PDF.` - ); - } - } - } catch (err) { - logger.error(err); // 404 for the savedObjectId, etc - throw err; - } - - const transformedJobParams = { - objectType, - title: reportTitle, - relativeUrls: kibanaRelativeUrls, - browserTimezone, - layout, - }; - - return await createJobFn(transformedJobParams, headers, request); - }; - }; -} diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/compatibility_shim.test.js b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/compatibility_shim.test.js deleted file mode 100644 index b3b8bca1d89555..00000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/compatibility_shim.test.js +++ /dev/null @@ -1,297 +0,0 @@ -/* - * 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 { once } from 'lodash'; -import { compatibilityShimFactory } from './compatibility_shim'; - -const createMockServer = () => { - return { - expose: jest.fn(), //fool once_per_server - log: jest.fn(), - }; -}; - -const createMockLogger = () => ({ - warning: jest.fn(), - error: jest.fn(), -}); - -const createMockRequest = () => { - return { - getSavedObjectsClient: once(function() { - return { - get: jest.fn(), - }; - }), - }; -}; - -test(`passes title through if provided`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - const title = 'test title'; - - const createJobMock = jest.fn(); - await compatibilityShim(createJobMock)( - { title, relativeUrls: ['/something'] }, - null, - createMockRequest() - ); - - expect(mockLogger.warning.mock.calls.length).toBe(0); - expect(mockLogger.error.mock.calls.length).toBe(0); - - expect(createJobMock.mock.calls.length).toBe(1); - expect(createJobMock.mock.calls[0][0].title).toBe(title); -}); - -test(`gets the title from the savedObject`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - - const createJobMock = jest.fn(); - const mockRequest = createMockRequest(); - const title = 'savedTitle'; - mockRequest.getSavedObjectsClient().get.mockReturnValue({ - attributes: { - title, - }, - }); - - await compatibilityShim(createJobMock)( - { objectType: 'search', savedObjectId: 'abc' }, - null, - mockRequest - ); - - expect(mockLogger.warning.mock.calls.length).toBe(2); - expect(mockLogger.warning.mock.calls[0][0]).toEqual( - 'The relativeUrls have been derived from saved object parameters. This functionality will be removed with the next major version.' - ); - expect(mockLogger.error.mock.calls.length).toBe(0); - - expect(createJobMock.mock.calls.length).toBe(1); - expect(createJobMock.mock.calls[0][0].title).toBe(title); -}); - -test(`passes the objectType and savedObjectId to the savedObjectsClient`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - - const createJobMock = jest.fn(); - const mockRequest = createMockRequest(); - mockRequest.getSavedObjectsClient().get.mockReturnValue({ - attributes: { - title: '', - }, - }); - - const objectType = 'search'; - const savedObjectId = 'abc'; - await compatibilityShim(createJobMock)({ objectType, savedObjectId }, null, mockRequest); - - expect(mockLogger.warning.mock.calls.length).toBe(2); - expect(mockLogger.warning.mock.calls[0][0]).toEqual( - 'The relativeUrls have been derived from saved object parameters. This functionality will be removed with the next major version.' - ); - expect(mockLogger.warning.mock.calls[1][0]).toEqual( - 'The title has been derived from saved object parameters. This functionality will be removed with the next major version.' - ); - expect(mockLogger.error.mock.calls.length).toBe(0); - - const getMock = mockRequest.getSavedObjectsClient().get.mock; - expect(getMock.calls.length).toBe(1); - expect(getMock.calls[0][0]).toBe(objectType); - expect(getMock.calls[0][1]).toBe(savedObjectId); -}); - -test(`logs no warnings when title and relativeUrls is passed`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - - const createJobMock = jest.fn(); - const mockRequest = createMockRequest(); - - await compatibilityShim(createJobMock)( - { title: 'Phenomenal Dashboard', relativeUrls: ['/abc', '/def'] }, - null, - mockRequest - ); - - expect(mockLogger.warning.mock.calls.length).toBe(0); - expect(mockLogger.error.mock.calls.length).toBe(0); -}); - -test(`logs warning if title can not be provided`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - - const createJobMock = jest.fn(); - const mockRequest = createMockRequest(); - await compatibilityShim(createJobMock)({ relativeUrls: ['/abc'] }, null, mockRequest); - - expect(mockLogger.warning.mock.calls.length).toBe(1); - expect(mockLogger.warning.mock.calls[0][0]).toEqual( - `A title parameter should be provided with the job generation request. Please ` + - `use Kibana to regenerate your POST URL to have a title included in the PDF.` - ); -}); - -test(`logs deprecations when generating the title/relativeUrl using the savedObject`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - - const createJobMock = jest.fn(); - const mockRequest = createMockRequest(); - mockRequest.getSavedObjectsClient().get.mockReturnValue({ - attributes: { - title: '', - }, - }); - - await compatibilityShim(createJobMock)( - { objectType: 'search', savedObjectId: 'abc' }, - null, - mockRequest - ); - - expect(mockLogger.warning.mock.calls.length).toBe(2); - expect(mockLogger.warning.mock.calls[0][0]).toEqual( - 'The relativeUrls have been derived from saved object parameters. This functionality will be removed with the next major version.' - ); - expect(mockLogger.warning.mock.calls[1][0]).toEqual( - 'The title has been derived from saved object parameters. This functionality will be removed with the next major version.' - ); -}); - -test(`passes objectType through`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - - const createJobMock = jest.fn(); - const mockRequest = createMockRequest(); - - const objectType = 'foo'; - await compatibilityShim(createJobMock)( - { title: 'test', relativeUrls: ['/something'], objectType }, - null, - mockRequest - ); - - expect(mockLogger.warning.mock.calls.length).toBe(0); - expect(mockLogger.error.mock.calls.length).toBe(0); - - expect(createJobMock.mock.calls.length).toBe(1); - expect(createJobMock.mock.calls[0][0].objectType).toBe(objectType); -}); - -test(`passes the relativeUrls through`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - - const createJobMock = jest.fn(); - - const relativeUrls = ['/app/kibana#something', '/app/kibana#something-else']; - await compatibilityShim(createJobMock)({ title: 'test', relativeUrls }, null, null); - - expect(mockLogger.warning.mock.calls.length).toBe(0); - expect(mockLogger.error.mock.calls.length).toBe(0); - - expect(createJobMock.mock.calls.length).toBe(1); - expect(createJobMock.mock.calls[0][0].relativeUrls).toBe(relativeUrls); -}); - -const testSavedObjectRelativeUrl = (objectType, expectedUrl) => { - test(`generates the saved object relativeUrl for ${objectType}`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - const createJobMock = jest.fn(); - - await compatibilityShim(createJobMock)( - { title: 'test', objectType, savedObjectId: 'abc' }, - null, - null - ); - - expect(mockLogger.warning.mock.calls.length).toBe(1); - expect(mockLogger.warning.mock.calls[0][0]).toEqual( - 'The relativeUrls have been derived from saved object parameters. This functionality will be removed with the next major version.' - ); - expect(mockLogger.error.mock.calls.length).toBe(0); - - expect(createJobMock.mock.calls.length).toBe(1); - expect(createJobMock.mock.calls[0][0].relativeUrls).toEqual([expectedUrl]); - }); -}; - -testSavedObjectRelativeUrl('search', '/app/kibana#/discover/abc?'); -testSavedObjectRelativeUrl('visualization', '/app/kibana#/visualize/edit/abc?'); -testSavedObjectRelativeUrl('dashboard', '/app/kibana#/dashboard/abc?'); - -test(`appends the queryString to the relativeUrl when generating from the savedObject`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - const createJobMock = jest.fn(); - - await compatibilityShim(createJobMock)( - { title: 'test', objectType: 'search', savedObjectId: 'abc', queryString: 'foo=bar' }, - null, - null - ); - - expect(mockLogger.warning.mock.calls.length).toBe(1); - expect(mockLogger.warning.mock.calls[0][0]).toEqual( - 'The relativeUrls have been derived from saved object parameters. This functionality will be removed with the next major version.' - ); - expect(mockLogger.error.mock.calls.length).toBe(0); - - expect(createJobMock.mock.calls.length).toBe(1); - expect(createJobMock.mock.calls[0][0].relativeUrls).toEqual([ - '/app/kibana#/discover/abc?foo=bar', - ]); -}); - -test(`throw an Error if the objectType, savedObjectId and relativeUrls are provided`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - const createJobMock = jest.fn(); - - const promise = compatibilityShim(createJobMock)( - { - title: 'test', - objectType: 'something', - relativeUrls: ['/something'], - savedObjectId: 'abc', - }, - null, - null - ); - - await expect(promise).rejects.toBeDefined(); -}); - -test(`passes headers and request through`, async () => { - const mockLogger = createMockLogger(); - const compatibilityShim = compatibilityShimFactory(createMockServer(), mockLogger); - - const createJobMock = jest.fn(); - - const headers = {}; - const request = createMockRequest(); - - await compatibilityShim(createJobMock)( - { title: 'test', relativeUrls: ['/something'] }, - headers, - request - ); - - expect(mockLogger.warning.mock.calls.length).toBe(0); - expect(mockLogger.error.mock.calls.length).toBe(0); - - expect(createJobMock.mock.calls.length).toBe(1); - expect(createJobMock.mock.calls[0][1]).toBe(headers); - expect(createJobMock.mock.calls[0][2]).toBe(request); -}); diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/index.ts index d17713057abc1e..a8cc71175cffeb 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/create_job/index.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PLUGIN_ID, PDF_JOB_TYPE } from '../../../../common/constants'; import { CreateJobFactory, ESQueueCreateJobFn, @@ -13,29 +12,16 @@ import { ConditionalHeaders, } from '../../../../types'; import { validateUrls } from '../../../../common/validate_urls'; -import { LevelLogger } from '../../../../server/lib'; import { cryptoFactory } from '../../../../server/lib/crypto'; import { JobParamsPDF } from '../../types'; -// @ts-ignore untyped module -import { compatibilityShimFactory } from './compatibility_shim'; - -interface CreateJobFnOpts { - objectType: any; - title: string; - relativeUrls: string[]; - browserTimezone: string; - layout: any; -} export const createJobFactory: CreateJobFactory> = function createJobFactoryFn(server: ServerFacade) { - const logger = LevelLogger.createForServer(server, [PLUGIN_ID, PDF_JOB_TYPE, 'create']); - const compatibilityShim = compatibilityShimFactory(server, logger); const crypto = cryptoFactory(server); - return compatibilityShim(async function createJobFn( - { objectType, title, relativeUrls, browserTimezone, layout }: CreateJobFnOpts, + return async function createJobFn( + { title, relativeUrls, browserTimezone, layout, objectType }: JobParamsPDF, headers: ConditionalHeaders['headers'], request: RequestFacade ) { @@ -44,14 +30,14 @@ export const createJobFactory: CreateJobFactory ({ relativeUrl: u })), - headers: serializedEncryptedHeaders, - browserTimezone, - layout, basePath: request.getBasePath(), + browserTimezone, forceNow: new Date().toISOString(), + headers: serializedEncryptedHeaders, + layout, + relativeUrls, + title, + objectType, }; - }); + }; }; diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js index db7b599a1aaabb..ddbee6e9d54a46 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js @@ -27,7 +27,8 @@ beforeEach(() => { 'server.port': 5601, }; mockServer = { - expose: () => {}, + expose: jest.fn(), + log: jest.fn(), config: memoize(() => ({ get: jest.fn() })), info: { protocol: 'http', @@ -71,7 +72,7 @@ test(`passes browserTimezone to generatePdf`, async () => { const browserTimezone = 'UTC'; await executeJob( 'pdfJobId', - { objects: [], browserTimezone, headers: encryptedHeaders }, + { relativeUrls: [], browserTimezone, headers: encryptedHeaders }, cancellationToken ); @@ -96,7 +97,7 @@ test(`returns content_type of application/pdf`, async () => { const { content_type: contentType } = await executeJob( 'pdfJobId', - { objects: [], timeRange: {}, headers: encryptedHeaders }, + { relativeUrls: [], timeRange: {}, headers: encryptedHeaders }, cancellationToken ); expect(contentType).toBe('application/pdf'); @@ -112,7 +113,7 @@ test(`returns content of generatePdf getBuffer base64 encoded`, async () => { const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pdfJobId', - { objects: [], timeRange: {}, headers: encryptedHeaders }, + { relativeUrls: [], timeRange: {}, headers: encryptedHeaders }, cancellationToken ); diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts index b51a2d4d5711c8..0a9dcfe986ca63 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts @@ -9,7 +9,7 @@ import { JobDocPayload, ServerFacade, RequestFacade } from '../../types'; // Job params: structure of incoming user request data, after being parsed from RISON export interface JobParamsPDF { - objectType: string; + objectType: string; // visualization, dashboard, etc. Used for job info & telemetry title: string; relativeUrls: string[]; browserTimezone: string; @@ -22,7 +22,5 @@ export interface JobDocPayloadPDF extends JobDocPayload { browserTimezone: string; forceNow?: string; layout: LayoutParams; - objects: Array<{ - relativeUrl: string; - }>; + relativeUrls: string[]; } diff --git a/x-pack/legacy/plugins/reporting/public/components/report_listing.tsx b/x-pack/legacy/plugins/reporting/public/components/report_listing.tsx index 9783372aa29c4b..320f6220aa9968 100644 --- a/x-pack/legacy/plugins/reporting/public/components/report_listing.tsx +++ b/x-pack/legacy/plugins/reporting/public/components/report_listing.tsx @@ -425,7 +425,7 @@ class ReportListingUi extends Component { return { id: job._id, type: source.jobtype, - object_type: source.payload.type, + object_type: source.payload.objectType, object_title: source.payload.title, created_by: source.created_by, created_at: source.created_at, diff --git a/x-pack/legacy/plugins/reporting/server/lib/esqueue/helpers/create_index.js b/x-pack/legacy/plugins/reporting/server/lib/esqueue/helpers/create_index.js index 9e00f0447e99e4..670c2907fb8322 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/esqueue/helpers/create_index.js +++ b/x-pack/legacy/plugins/reporting/server/lib/esqueue/helpers/create_index.js @@ -15,7 +15,7 @@ const schema = { properties: { /** * Type of object that is triggering this report. Should be either search, visualization or dashboard. - * Used for phone home stats only. + * Used for job listing and telemetry stats only. */ objectType: { type: 'text', diff --git a/x-pack/legacy/plugins/reporting/server/lib/esqueue/job.js b/x-pack/legacy/plugins/reporting/server/lib/esqueue/job.js index cded6d2ce89a8c..a7d8f4df3fd541 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/esqueue/job.js +++ b/x-pack/legacy/plugins/reporting/server/lib/esqueue/job.js @@ -57,7 +57,7 @@ export class Job extends events.EventEmitter { meta: { // We are copying these values out of payload because these fields are indexed and can be aggregated on // for tracking stats, while payload contents are not. - objectType: payload.type, + objectType: payload.objectType, layout: payload.layout ? payload.layout.id : 'none', }, payload: this.payload, diff --git a/x-pack/legacy/plugins/reporting/server/routes/generation.ts b/x-pack/legacy/plugins/reporting/server/routes/generation.ts index 7bed7bc5773e45..73450b7641c8e4 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generation.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generation.ts @@ -17,7 +17,6 @@ import { import { registerGenerateFromJobParams } from './generate_from_jobparams'; import { registerGenerateCsvFromSavedObject } from './generate_from_savedobject'; import { registerGenerateCsvFromSavedObjectImmediate } from './generate_from_savedobject_immediate'; -import { registerLegacy } from './legacy'; import { createQueueFactory, enqueueJobFactory } from '../lib'; export function registerJobGenerationRoutes( @@ -73,7 +72,6 @@ export function registerJobGenerationRoutes( } registerGenerateFromJobParams(server, handler, handleError); - registerLegacy(server, handler, handleError); // Register beta panel-action download-related API's if (config.get('xpack.reporting.csv.enablePanelActionDownload')) { diff --git a/x-pack/legacy/plugins/reporting/server/routes/legacy.ts b/x-pack/legacy/plugins/reporting/server/routes/legacy.ts deleted file mode 100644 index 011ac4a02bbf9e..00000000000000 --- a/x-pack/legacy/plugins/reporting/server/routes/legacy.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 querystring from 'querystring'; -import { API_BASE_URL } from '../../common/constants'; -import { ServerFacade, RequestFacade, ReportingResponseToolkit } from '../../types'; -import { - getRouteConfigFactoryReportingPre, - GetRouteConfigFactoryFn, -} from './lib/route_config_factories'; -import { HandlerErrorFunction, HandlerFunction } from './types'; - -const getStaticFeatureConfig = (getRouteConfig: GetRouteConfigFactoryFn, featureId: string) => - getRouteConfig(() => featureId); - -const BASE_GENERATE = `${API_BASE_URL}/generate`; - -export function registerLegacy( - server: ServerFacade, - handler: HandlerFunction, - handleError: HandlerErrorFunction -) { - const getRouteConfig = getRouteConfigFactoryReportingPre(server); - - function createLegacyPdfRoute({ path, objectType }: { path: string; objectType: string }) { - const exportTypeId = 'printablePdf'; - server.route({ - path, - method: 'POST', - options: getStaticFeatureConfig(getRouteConfig, exportTypeId), - handler: async (request: RequestFacade, h: ReportingResponseToolkit) => { - const message = `The following URL is deprecated and will stop working in the next major version: ${request.url.path}`; - server.log(['warning', 'reporting', 'deprecation'], message); - - try { - const savedObjectId = request.params.savedId; - const queryString = querystring.stringify(request.query); - - return await handler( - exportTypeId, - { - objectType, - savedObjectId, - queryString, - }, - request, - h - ); - } catch (err) { - throw handleError(exportTypeId, err); - } - }, - }); - } - - createLegacyPdfRoute({ - path: `${BASE_GENERATE}/visualization/{savedId}`, - objectType: 'visualization', - }); - - createLegacyPdfRoute({ - path: `${BASE_GENERATE}/search/{savedId}`, - objectType: 'search', - }); - - createLegacyPdfRoute({ - path: `${BASE_GENERATE}/dashboard/{savedId}`, - objectType: 'dashboard', - }); -} diff --git a/x-pack/test/reporting/README.md b/x-pack/test/reporting/README.md index 30859fa96c015a..d4a6c20a835e22 100644 --- a/x-pack/test/reporting/README.md +++ b/x-pack/test/reporting/README.md @@ -82,16 +82,6 @@ node scripts/functional_tests_server.js --config test/reporting/configs/chromium **Note:** Dashboard has some snapshot testing too, in `_dashboard_snapshots.js`. This test watches for a command line flag `--updateBaselines` which automates updating the baselines. Probably worthwhile to do some similar here in the long run. - ### Adding a new BWC test - - We have tests that ensure the latest version of Kibana will continue to generate reports from URLs generated in previous versions, to ensure backward compatibility. These tests are in `api/bwc_generation_urls.js`. It's important to update these every now and then and add new ones, especially if anything in the URL changed in a release. - - To add test coverage for a specific minor release,: -1. Checkout previous branch, e.g. `git checkout upstream/6.4` -2. Sync your environment via `yarn kbn bootstrap` (Note, if you run into problems you may want to first clean via `yarn kbn clean`) -3. Start up kibana and Elasticsearch (`yarn es snapshot --license trial` in one terminal, and `yarn start` in another) -4. Load the reporting test data that is used in the tests. Ensure you are in the `x-pack` directory and run: - ``` node ../scripts/es_archiver.js --es-url http://elastic:changeme@localhost:9200 load ../../../../test/functional/fixtures/es_archiver/dashboard/current/kibana ``` diff --git a/x-pack/test/reporting/api/bwc_existing_indexes.js b/x-pack/test/reporting/api/bwc_existing_indexes.js deleted file mode 100644 index ffcf123848bb2e..00000000000000 --- a/x-pack/test/reporting/api/bwc_existing_indexes.js +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 * as GenerationUrls from './generation_urls'; - -/** - * This file tests the situation when a reporting index spans releases. By default reporting indexes are created - * on a weekly basis, but this is configurable so it is possible a user has this set to yearly. In that event, it - * is possible report data is getting posted to an index that was created by a very old version. We don't have a - * reporting index migration plan, so this test is important to ensure BWC, or that in the event we decide to make - * a major change in a major release, we handle it properly. - */ - -export default function({ getService }) { - const esArchiver = getService('esArchiver'); - const reportingAPI = getService('reportingAPI'); - const usageAPI = getService('usageAPI'); - - // FLAKY: https://github.com/elastic/kibana/issues/42725 - describe.skip('BWC report generation into existing indexes', () => { - let expectedCompletedReportCount; - let cleanupIndexAlias; - - describe('existing 6_2 index', () => { - before('load data and add index alias', async () => { - await reportingAPI.deleteAllReportingIndexes(); - await esArchiver.load('reporting/bwc/6_2'); - - // The index name in the 6_2 archive. - const ARCHIVED_REPORTING_INDEX = '.reporting-2018.03.11'; - cleanupIndexAlias = await reportingAPI.coerceReportsIntoExistingIndex( - ARCHIVED_REPORTING_INDEX - ); - - const stats = await usageAPI.getUsageStats(); - expectedCompletedReportCount = await reportingAPI.getCompletedReportCount(stats); - - await esArchiver.unload('reporting/bwc/6_2'); - }); - - after('remove index alias', async () => { - await cleanupIndexAlias(); - }); - - // Might not be great test practice to lump all these jobs together but reporting takes awhile and it'll be - // more efficient to post them all up front, then sequentially. - it('multiple jobs posted', async () => { - const reportPaths = []; - reportPaths.push( - await reportingAPI.postJob(GenerationUrls.CSV_DISCOVER_KUERY_AND_FILTER_6_3) - ); - reportPaths.push( - await reportingAPI.postJob(GenerationUrls.PDF_PRESERVE_DASHBOARD_FILTER_6_3) - ); - reportPaths.push( - await reportingAPI.postJob(GenerationUrls.PDF_PRESERVE_PIE_VISUALIZATION_6_3) - ); - reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRINT_DASHBOARD_6_3)); - reportPaths.push( - await reportingAPI.postJob( - GenerationUrls.PDF_PRINT_PIE_VISUALIZATION_FILTER_AND_SAVED_SEARCH_6_3 - ) - ); - - await reportingAPI.expectAllJobsToFinishSuccessfully(reportPaths); - }).timeout(1540000); - - it('jobs completed successfully', async () => { - const stats = await usageAPI.getUsageStats(); - expectedCompletedReportCount += 5; - reportingAPI.expectCompletedReportCount(stats, expectedCompletedReportCount); - }); - }); - }); -} diff --git a/x-pack/test/reporting/api/bwc_generation_urls.js b/x-pack/test/reporting/api/bwc_generation_urls.js deleted file mode 100644 index 25b40ff3f74a82..00000000000000 --- a/x-pack/test/reporting/api/bwc_generation_urls.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 * as GenerationUrls from './generation_urls'; - -export default function({ getService }) { - const reportingAPI = getService('reportingAPI'); - const usageAPI = getService('usageAPI'); - - describe('BWC report generation urls', () => { - describe('Pre 6_2', () => { - before(async () => { - await reportingAPI.deleteAllReportingIndexes(); - }); - - // The URL being tested was captured from release 6.4 and then the layout section was removed to test structure before - // preserve_layout was introduced. See https://github.com/elastic/kibana/issues/23414 - it('job posted successfully', async () => { - const path = await reportingAPI.postJob(GenerationUrls.PDF_PRINT_DASHBOARD_PRE_6_2); - await reportingAPI.waitForJobToFinish(path); - const stats = await usageAPI.getUsageStats(); - reportingAPI.expectCompletedReportCount(stats, 1); - }).timeout(500000); - }); - - describe('6_2', () => { - before(async () => { - await reportingAPI.deleteAllReportingIndexes(); - }); - - // Might not be great test practice to lump all these jobs together but reporting takes awhile and it'll be - // more efficient to post them all up front, then sequentially. - it('multiple jobs posted', async () => { - const reportPaths = []; - reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRINT_DASHBOARD_6_2)); - reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRESERVE_VISUALIZATION_6_2)); - reportPaths.push(await reportingAPI.postJob(GenerationUrls.CSV_DISCOVER_FILTER_QUERY_6_2)); - - await reportingAPI.expectAllJobsToFinishSuccessfully(reportPaths); - }).timeout(1540000); - - it('jobs completed successfully', async () => { - const stats = await usageAPI.getUsageStats(); - reportingAPI.expectCompletedReportCount(stats, 3); - }); - }); - - // 6.3 urls currently being tested as part of the "bwc_existing_indexes" test suite. Reports are time consuming, - // don't replicate tests if we don't need to, so no specific 6_3 url tests here. - }); -} diff --git a/x-pack/test/reporting/api/chromium_tests.js b/x-pack/test/reporting/api/chromium_tests.js index 6594a80db491b1..2d5a31bb40da32 100644 --- a/x-pack/test/reporting/api/chromium_tests.js +++ b/x-pack/test/reporting/api/chromium_tests.js @@ -27,8 +27,6 @@ export default function({ loadTestFile, getService }) { await esArchiver.unload(OSS_DATA_ARCHIVE_PATH); }); - loadTestFile(require.resolve('./bwc_existing_indexes')); - loadTestFile(require.resolve('./bwc_generation_urls')); loadTestFile(require.resolve('./usage')); }); } diff --git a/x-pack/test/reporting/api/generation_urls.js b/x-pack/test/reporting/api/generation_urls.js index 182d395704a25b..b98b1a26651a15 100644 --- a/x-pack/test/reporting/api/generation_urls.js +++ b/x-pack/test/reporting/api/generation_urls.js @@ -4,13 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -// These all have the domain name portion stripped out. The api infrastructure assumes it when we post to it anyhow. - -// The URL below was captured from release 6.4 and then the layout section was removed to test structure before -// preserve_layout was introduced. See https://github.com/elastic/kibana/issues/23414 -export const PDF_PRINT_DASHBOARD_PRE_6_2 = - '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,objectType:dashboard,relativeUrls:!(%27%2Fapp%2Fkibana%23%2Fdashboard%2F2ae34a60-3dd4-11e8-b2b9-5d5dc1715159%3F_g%3D(refreshInterval:(pause:!!t,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(description:!%27!%27,filters:!!(),fullScreenMode:!!f,options:(hidePanelTitles:!!f,useMargins:!!t),panels:!!((embeddableConfig:(),gridData:(h:15,i:!%271!%27,w:24,x:0,y:0),id:!%27145ced90-3dcb-11e8-8660-4d65aa086b3c!%27,panelIndex:!%271!%27,type:visualization,version:!%276.3.0!%27),(embeddableConfig:(),gridData:(h:15,i:!%272!%27,w:24,x:24,y:0),id:e2023110-3dcb-11e8-8660-4d65aa086b3c,panelIndex:!%272!%27,type:visualization,version:!%276.3.0!%27)),query:(language:lucene,query:!%27!%27),timeRestore:!!f,title:!%27couple%2Bpanels!%27,viewMode:view)%27),title:%27couple%20panels%27)'; - export const PDF_PRINT_DASHBOARD_6_3 = '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(id:print),objectType:dashboard,relativeUrls:!(%27%2Fapp%2Fkibana%23%2Fdashboard%2F2ae34a60-3dd4-11e8-b2b9-5d5dc1715159%3F_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(description:!%27!%27,filters:!!(),fullScreenMode:!!f,options:(hidePanelTitles:!!f,useMargins:!!t),panels:!!((embeddableConfig:(),gridData:(h:15,i:!%271!%27,w:24,x:0,y:0),id:!%27145ced90-3dcb-11e8-8660-4d65aa086b3c!%27,panelIndex:!%271!%27,type:visualization,version:!%276.3.0!%27),(embeddableConfig:(),gridData:(h:15,i:!%272!%27,w:24,x:24,y:0),id:e2023110-3dcb-11e8-8660-4d65aa086b3c,panelIndex:!%272!%27,type:visualization,version:!%276.3.0!%27)),query:(language:lucene,query:!%27!%27),timeRestore:!!f,title:!%27couple%2Bpanels!%27,viewMode:view)%27),title:%27couple%20panels%27)'; export const PDF_PRESERVE_DASHBOARD_FILTER_6_3 = @@ -21,10 +14,3 @@ export const PDF_PRINT_PIE_VISUALIZATION_FILTER_AND_SAVED_SEARCH_6_3 = '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(id:print),objectType:visualization,relativeUrls:!(%27%2Fapp%2Fkibana%23%2Fvisualize%2Fedit%2Fbefdb6b0-3e59-11e8-9fc3-39e49624228e%3F_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(filters:!!((!%27$state!%27:(store:appState),meta:(alias:!!n,disabled:!!f,index:a0f483a0-3dc9-11e8-8660-4d65aa086b3c,key:animal.keyword,negate:!!f,params:(query:dog,type:phrase),type:phrase,value:dog),query:(match:(animal.keyword:(query:dog,type:phrase))))),linked:!!t,query:(language:lucene,query:!%27!%27),uiState:(),vis:(aggs:!!((enabled:!!t,id:!%271!%27,params:(),schema:metric,type:count),(enabled:!!t,id:!%272!%27,params:(field:name.keyword,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27,otherBucket:!!f,otherBucketLabel:Other,size:5),schema:segment,type:terms)),params:(addLegend:!!t,addTooltip:!!t,isDonut:!!t,labels:(last_level:!!t,show:!!f,truncate:100,values:!!t),legendPosition:right,type:pie),title:!%27Filter%2BTest:%2Banimals:%2Blinked%2Bto%2Bsearch%2Bwith%2Bfilter!%27,type:pie))%27),title:%27Filter%20Test:%20animals:%20linked%20to%20search%20with%20filter%27)'; export const CSV_DISCOVER_KUERY_AND_FILTER_6_3 = '/api/reporting/generate/csv?jobParams=(conflictedTypesFields:!(),fields:!(%27@timestamp%27,agent,bytes,clientip),indexPatternId:%270bf35f60-3dc9-11e8-8660-4d65aa086b3c%27,metaFields:!(_source,_id,_type,_index,_score),searchRequest:(body:(_source:(excludes:!(),includes:!(%27@timestamp%27,agent,bytes,clientip)),docvalue_fields:!(%27@timestamp%27),query:(bool:(filter:!((bool:(minimum_should_match:1,should:!((match:(clientip:%2773.14.212.83%27)))))),must:!((range:(bytes:(gte:100,lt:1000))),(range:(%27@timestamp%27:(format:epoch_millis,gte:1369165215770,lte:1526931615770)))),must_not:!(),should:!())),script_fields:(),sort:!((%27@timestamp%27:(order:desc,unmapped_type:boolean))),stored_fields:!(%27@timestamp%27,agent,bytes,clientip),version:!t),index:%27logstash-*%27),title:%27Bytes%20and%20kuery%20in%20saved%20search%20with%20filter%27,type:search)'; - -export const PDF_PRINT_DASHBOARD_6_2 = - '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(id:print),objectType:dashboard,queryString:%27_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(description:!%27!%27,filters:!!((!%27$state!%27:(store:appState),meta:(alias:!!n,disabled:!!f,field:isDog,index:a0f483a0-3dc9-11e8-8660-4d65aa086b3c,key:isDog,negate:!!f,params:(value:!!t),type:phrase,value:true),script:(script:(inline:!%27boolean%2Bcompare(Supplier%2Bs,%2Bdef%2Bv)%2B%257Breturn%2Bs.get()%2B%253D%253D%2Bv%3B%257Dcompare(()%2B-%253E%2B%257B%2Breturn%2Bdoc%255B!!!%27animal.keyword!!!%27%255D.value%2B%253D%253D%2B!!!%27dog!!!%27%2B%257D,%2Bparams.value)%3B!%27,lang:painless,params:(value:!!t))))),fullScreenMode:!!f,options:(hidePanelTitles:!!f,useMargins:!!t),panels:!!((gridData:(h:3,i:!%274!%27,w:6,x:6,y:0),id:edb65990-53ca-11e8-b481-c9426d020fcd,panelIndex:!%274!%27,type:visualization,version:!%276.2.4!%27),(gridData:(h:3,i:!%275!%27,w:6,x:0,y:0),id:!%270644f890-53cb-11e8-b481-c9426d020fcd!%27,panelIndex:!%275!%27,type:visualization,version:!%276.2.4!%27)),query:(language:lucene,query:!%27weightLbs:%253E15!%27),timeRestore:!!t,title:!%27Animal%2BWeights%2B(created%2Bin%2B6.2)!%27,viewMode:view)%27,savedObjectId:%271b2f47b0-53cb-11e8-b481-c9426d020fcd%27)'; -export const PDF_PRESERVE_VISUALIZATION_6_2 = - '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(dimensions:(height:441,width:1002),id:preserve_layout),objectType:visualization,queryString:%27_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(filters:!!(),linked:!!f,query:(language:lucene,query:!%27weightLbs:%253E10!%27),uiState:(),vis:(aggs:!!((enabled:!!t,id:!%271!%27,params:(),schema:metric,type:count),(enabled:!!t,id:!%272!%27,params:(field:weightLbs,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27,otherBucket:!!f,otherBucketLabel:Other,size:5),schema:segment,type:terms)),params:(addLegend:!!t,addTooltip:!!t,isDonut:!!t,labels:(last_level:!!t,show:!!f,truncate:100,values:!!t),legendPosition:right,type:pie),title:!%27Weight%2Bin%2Blbs%2Bpie%2Bcreated%2Bin%2B6.2!%27,type:pie))%27,savedObjectId:%270644f890-53cb-11e8-b481-c9426d020fcd%27)'; -export const CSV_DISCOVER_FILTER_QUERY_6_2 = - '/api/reporting/generate/csv?jobParams=(conflictedTypesFields:!(),fields:!(%27@timestamp%27,animal,sound,weightLbs),indexPatternId:a0f483a0-3dc9-11e8-8660-4d65aa086b3c,metaFields:!(_source,_id,_type,_index,_score),searchRequest:(body:(_source:(excludes:!(),includes:!(%27@timestamp%27,animal,sound,weightLbs)),docvalue_fields:!(%27@timestamp%27),query:(bool:(filter:!(),must:!((query_string:(analyze_wildcard:!t,default_field:%27*%27,query:%27weightLbs:%3E10%27)),(match_phrase:(sound.keyword:(query:growl))),(range:(%27@timestamp%27:(format:epoch_millis,gte:1523310968000,lte:1523483768000)))),must_not:!(),should:!())),script_fields:(),sort:!((%27@timestamp%27:(order:desc,unmapped_type:boolean))),stored_fields:!(%27@timestamp%27,animal,sound,weightLbs),version:!t),index:%27animals-*%27),title:%27Search%20created%20in%206.2%27,type:search)';