diff --git a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js index 2a101609ebe51e..b653e52f97e109 100644 --- a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js +++ b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js @@ -13,16 +13,24 @@ import { stringify } from 'query-string'; import { registerHelpers } from './rollup.test_helpers'; import { getRandomString } from './lib'; import { DataViewType } from '@kbn/data-views-plugin/common'; +import { INDEX_TO_ROLLUP_MAPPINGS } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); - const { createIndexWithMappings, getJobPayload, createJob, cleanUp } = + const { createIndexWithMappings, createMockRollupIndex, getJobPayload, createJob, cleanUp } = registerHelpers(getService); describe('index patterns extension', () => { - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/184081 - describe.skip('Fields for wildcards', () => { + // From 8.15, Es only allows creating a new rollup job when there is existing rollup usage in the cluster + // We will simulate rollup usage by creating a mock-up rollup index + before(async () => { + await createMockRollupIndex(); + }); + + after(() => cleanUp()); + + describe('Fields for wildcards', () => { describe('query params validation', () => { let uri; let body; @@ -57,7 +65,7 @@ export default function ({ getService }) { it('should return the correct fields', async () => { // Create a Rollup job on an index with the INDEX_TO_ROLLUP_MAPPINGS - const indexName = await createIndexWithMappings(); + const indexName = await createIndexWithMappings(undefined, INDEX_TO_ROLLUP_MAPPINGS); const rollupIndex = getRandomString(); const payload = getJobPayload(indexName, undefined, rollupIndex); await createJob(payload); @@ -65,7 +73,6 @@ export default function ({ getService }) { // Query for wildcard const params = { pattern: indexName, - type: DataViewType.ROLLUP, rollup_index: rollupIndex, }; const uri = `${BASE_URI}?${stringify(params, { sort: false })}`; @@ -75,12 +82,12 @@ export default function ({ getService }) { .expect(200); // Verify that the fields for wildcard correspond to our declared mappings - // noting that testTotalField and testTagField are not shown in the field caps results const fieldsForWildcard = body.fields.map((field) => field.name); - expect(fieldsForWildcard.sort()).eql(['testCreatedField']); - - // Cleanup - await cleanUp(); + expect(fieldsForWildcard.sort()).eql([ + 'testCreatedField', + 'testTagField', + 'testTotalField', + ]); }); }); }); diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup.js b/x-pack/test/api_integration/apis/management/rollup/rollup.js index a44da818a94e4d..16e7921ff1c2e4 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup.js @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { API_BASE_PATH, ROLLUP_INDEX_NAME } from './constants'; +import { API_BASE_PATH, INDEX_TO_ROLLUP_MAPPINGS, ROLLUP_INDEX_NAME } from './constants'; import { registerHelpers } from './rollup.test_helpers'; @@ -15,6 +15,7 @@ export default function ({ getService }) { const { createIndexWithMappings, + createMockRollupIndex, getJobPayload, loadJobs, createJob, @@ -24,8 +25,7 @@ export default function ({ getService }) { cleanUp, } = registerHelpers(getService); - // Failing: See https://github.com/elastic/kibana/issues/184073 - describe.skip('jobs', () => { + describe('jobs', () => { after(() => cleanUp()); describe('indices', () => { @@ -84,212 +84,231 @@ export default function ({ getService }) { }); }); - describe('crud', () => { - describe('list', () => { - it('should return an empty array when there are no jobs', async () => { - const { body } = await loadJobs().expect(200); + describe('with no rollup usage in the cluster', () => { + // From 8.15, Es only allows creating a new rollup job when there is existing rollup usage in the cluster + // The test cluster doesn't currently have any rollup usage so creation of a rollup job should fail + it('should throw a 400 error when trying to create a rollup job', async () => { + const indexName = await createIndexWithMappings(); - expect(body).to.eql({ jobs: [] }); - }); + const payload = getJobPayload(indexName); + + return createJob(payload).expect(400); + }); + }); + + describe('with existing rollup usage in the cluster', () => { + // From 8.15, Es only allows creating a new rollup job when there is existing rollup usage in the cluster + // We will simulate rollup usage by creating a mock-up rollup index + before(async () => { + await createMockRollupIndex(); }); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/183928 - describe.skip('create', () => { - let indexName; + describe('crud', () => { + describe('list', () => { + it('should return an empty array when there are no jobs', async () => { + const { body } = await loadJobs().expect(200); - beforeEach(async () => { - indexName = await createIndexWithMappings(); + expect(body).to.eql({ jobs: [] }); + }); }); - it('should create a rollup job', async () => { - const payload = getJobPayload(indexName); + describe('create', () => { + let indexName; - return createJob(payload).expect(200); - }); + beforeEach(async () => { + indexName = await createIndexWithMappings(undefined, INDEX_TO_ROLLUP_MAPPINGS); + }); - it('should throw a 409 conflict when trying to create 2 jobs with the same id', async () => { - const payload = getJobPayload(indexName); + it('should create a rollup job', async () => { + const payload = getJobPayload(indexName); - await createJob(payload); + return createJob(payload).expect(200); + }); - return createJob(payload).expect(409); - }); + it('should throw a 409 conflict when trying to create 2 jobs with the same id', async () => { + const payload = getJobPayload(indexName); - it('should handle ES errors', async () => { - const payload = { job: { id: 'abc', invalid: 'property' } }; + await createJob(payload); - const { body } = await createJob(payload); - expect(body.message).to.contain('unknown field [invalid]'); - }); + return createJob(payload).expect(409); + }); + + it('should handle ES errors', async () => { + const payload = { job: { id: 'abc', invalid: 'property' } }; - it('should list the newly created job', async () => { - const payload = getJobPayload(indexName); - await createJob(payload); + const { body } = await createJob(payload); + expect(body.message).to.contain('unknown field [invalid]'); + }); - const { - body: { jobs }, - } = await loadJobs(); - const job = jobs.find((job) => job.config.id === payload.job.id); + it('should list the newly created job', async () => { + const payload = getJobPayload(indexName); + await createJob(payload); - expect(job).not.be(undefined); - expect(job.config.index_pattern).to.eql(payload.job.index_pattern); - expect(job.config.rollup_index).to.eql(payload.job.rollup_index); - }); + const { + body: { jobs }, + } = await loadJobs(); + const job = jobs.find((job) => job.config.id === payload.job.id); - it('should create the underlying rollup index with the correct aggregations', async () => { - await createJob(getJobPayload(indexName)); - - const { body } = await supertest.get(`${API_BASE_PATH}/indices`); - - expect(body[ROLLUP_INDEX_NAME]).to.not.be(undefined); - - expect(body).to.eql({ - rollup_index: { - aggs: { - date_histogram: { - testCreatedField: { - agg: 'date_histogram', - delay: '1d', - // TODO: Note that we created the job with `interval`, but ES has coerced this to - // `fixed_interval` based on the value we provided. Once we update the UI and - // tests to no longer use the deprecated `interval` property, we can remove - // this comment. - fixed_interval: '24h', - time_zone: 'UTC', + expect(job).not.be(undefined); + expect(job.config.index_pattern).to.eql(payload.job.index_pattern); + expect(job.config.rollup_index).to.eql(payload.job.rollup_index); + }); + + it('should create the underlying rollup index with the correct aggregations', async () => { + await createJob(getJobPayload(indexName)); + + const { body } = await supertest.get(`${API_BASE_PATH}/indices`); + + expect(body[ROLLUP_INDEX_NAME]).to.not.be(undefined); + + expect(body).to.eql({ + rollup_index: { + aggs: { + date_histogram: { + testCreatedField: { + agg: 'date_histogram', + delay: '1d', + // TODO: Note that we created the job with `interval`, but ES has coerced this to + // `fixed_interval` based on the value we provided. Once we update the UI and + // tests to no longer use the deprecated `interval` property, we can remove + // this comment. + fixed_interval: '24h', + time_zone: 'UTC', + }, }, - }, - max: { - testCreatedField: { - agg: 'max', + max: { + testCreatedField: { + agg: 'max', + }, }, - }, - min: { - testCreatedField: { - agg: 'min', + min: { + testCreatedField: { + agg: 'min', + }, }, - }, - terms: { - testTagField: { - agg: 'terms', + terms: { + testTagField: { + agg: 'terms', + }, + testTotalField: { + agg: 'terms', + }, }, - testTotalField: { - agg: 'terms', + histogram: { + testTotalField: { + agg: 'histogram', + interval: 7, + }, }, - }, - histogram: { - testTotalField: { - agg: 'histogram', - interval: 7, + avg: { + testTotalField: { + agg: 'avg', + }, }, - }, - avg: { - testTotalField: { - agg: 'avg', - }, - }, - value_count: { - testTotalField: { - agg: 'value_count', + value_count: { + testTotalField: { + agg: 'value_count', + }, }, }, }, - }, + }); }); }); - }); - describe('delete', () => { - let jobId; + describe('delete', () => { + let jobId; - beforeEach(async () => { - const indexName = await createIndexWithMappings(); - const payload = getJobPayload(indexName); - jobId = payload.job.id; - await createJob(payload); - }); + beforeEach(async () => { + const indexName = await createIndexWithMappings(undefined, INDEX_TO_ROLLUP_MAPPINGS); + const payload = getJobPayload(indexName); + jobId = payload.job.id; + await createJob(payload); + }); - it('should delete a job that has been stopped', async () => { - await stopJob(jobId); - const { body } = await deleteJob(jobId).expect(200); - expect(body).to.eql({ success: true }); - }); + it('should delete a job that has been stopped', async () => { + await stopJob(jobId); + const { body } = await deleteJob(jobId).expect(200); + expect(body).to.eql({ success: true }); + }); - it('should throw a 400 error if trying to delete a job that is started', async () => { - await startJob(jobId); - const { body } = await deleteJob(jobId).expect(400); - expect(body.message).to.contain('Job must be [STOPPED] before deletion'); + it('should throw a 400 error if trying to delete a job that is started', async () => { + await startJob(jobId); + const { body } = await deleteJob(jobId).expect(400); + expect(body.message).to.contain('Job must be [STOPPED] before deletion'); + }); }); }); - }); - describe('actions', () => { - describe('start', () => { - let job; + describe('actions', () => { + describe('start', () => { + let job; - beforeEach(async () => { - const indexName = await createIndexWithMappings(); - const payload = getJobPayload(indexName); - await createJob(payload); + beforeEach(async () => { + const indexName = await createIndexWithMappings(undefined, INDEX_TO_ROLLUP_MAPPINGS); + const payload = getJobPayload(indexName); + await createJob(payload); - const { - body: { jobs }, - } = await loadJobs(); - job = jobs.find((job) => job.config.id === payload.job.id); - }); + const { + body: { jobs }, + } = await loadJobs(); + job = jobs.find((job) => job.config.id === payload.job.id); + }); - it('should start the job', async () => { - expect(job.status.job_state).to.eql('stopped'); + it('should start the job', async () => { + expect(job.status.job_state).to.eql('stopped'); - const { body } = await startJob(job.config.id).expect(200); + const { body } = await startJob(job.config.id).expect(200); - expect(body).to.eql({ success: true }); + expect(body).to.eql({ success: true }); - // Fetch the job to make sure it has been started - const jobId = job.config.id; - const { - body: { jobs }, - } = await loadJobs(); - job = jobs.find((job) => job.config.id === jobId); - expect(job.status.job_state).to.eql('started'); - }); + // Fetch the job to make sure it has been started + const jobId = job.config.id; + const { + body: { jobs }, + } = await loadJobs(); + job = jobs.find((job) => job.config.id === jobId); + expect(job.status.job_state).to.eql('started'); + }); - it('should return 200 if the job is already started', async () => { - await startJob(job.config.id); // Start the job - await startJob(job.config.id).expect(200); + it('should return 200 if the job is already started', async () => { + await startJob(job.config.id); // Start the job + await startJob(job.config.id).expect(200); + }); }); - }); - describe('stop', () => { - let job; + describe('stop', () => { + let job; - beforeEach(async () => { - const indexName = await createIndexWithMappings(); - const payload = getJobPayload(indexName); - await createJob(payload); + beforeEach(async () => { + const indexName = await createIndexWithMappings(undefined, INDEX_TO_ROLLUP_MAPPINGS); + const payload = getJobPayload(indexName); + await createJob(payload); - const { - body: { jobs }, - } = await loadJobs(); - job = jobs.find((job) => job.config.id === payload.job.id); - }); + const { + body: { jobs }, + } = await loadJobs(); + job = jobs.find((job) => job.config.id === payload.job.id); + }); - it('should stop the job', async () => { - await startJob(job.config.id); - const { body } = await stopJob(job.config.id).expect(200); + it('should stop the job', async () => { + await startJob(job.config.id); + const { body } = await stopJob(job.config.id).expect(200); - expect(body).to.eql({ success: true }); + expect(body).to.eql({ success: true }); - // Fetch the job to make sure it has been stopped - const jobId = job.config.id; - const { - body: { jobs }, - } = await loadJobs(); - job = jobs.find((job) => job.config.id === jobId); - expect(job.status.job_state).to.eql('stopped'); - }); + // Fetch the job to make sure it has been stopped + const jobId = job.config.id; + const { + body: { jobs }, + } = await loadJobs(); + job = jobs.find((job) => job.config.id === jobId); + expect(job.status.job_state).to.eql('stopped'); + }); - it('should return 200 if the job is already stopped', async () => { - await stopJob(job.config.id).expect(200); + it('should return 200 if the job is already stopped', async () => { + await stopJob(job.config.id).expect(200); + }); }); }); }); diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup.test_helpers.js b/x-pack/test/api_integration/apis/management/rollup/rollup.test_helpers.js index 85e5c0c5226997..a99b4137d3d090 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup.test_helpers.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup.test_helpers.js @@ -119,8 +119,50 @@ export const registerHelpers = (getService) => { throw err; }); + const createMockRollupIndex = () => + createIndexWithMappings('mock_rollup_index', { + _meta: { + _rollup: { + logs_job: { + id: 'mockRollupJob', + index_pattern: 'mockRollupIndex', + rollup_index: ROLLUP_INDEX_NAME, + cron: '0 0 0 ? * 7', + page_size: 1000, + groups: { + date_histogram: { + interval: '24h', + delay: '1d', + time_zone: 'UTC', + field: 'testCreatedField', + }, + terms: { + fields: ['testTotalField', 'testTagField'], + }, + histogram: { + interval: '7', + fields: ['testTotalField'], + }, + }, + metrics: [ + { + field: 'testTotalField', + metrics: ['avg', 'value_count'], + }, + { + field: 'testCreatedField', + metrics: ['max', 'min'], + }, + ], + }, + }, + 'rollup-version': '', + }, + }); + return { createIndexWithMappings, + createMockRollupIndex, getJobPayload, loadJobs, createJob, diff --git a/x-pack/test/api_integration/apis/management/rollup/rollup_search.js b/x-pack/test/api_integration/apis/management/rollup/rollup_search.js index 8d2fb780c9ff34..2ab2069cf9634e 100644 --- a/x-pack/test/api_integration/apis/management/rollup/rollup_search.js +++ b/x-pack/test/api_integration/apis/management/rollup/rollup_search.js @@ -8,17 +8,18 @@ import expect from '@kbn/expect'; import { registerHelpers } from './rollup.test_helpers'; -import { API_BASE_PATH } from './constants'; +import { API_BASE_PATH, INDEX_TO_ROLLUP_MAPPINGS } from './constants'; import { getRandomString } from './lib'; export default function ({ getService }) { const supertest = getService('supertest'); - const { createIndexWithMappings, getJobPayload, createJob, cleanUp } = + const { createIndexWithMappings, createMockRollupIndex, getJobPayload, createJob, cleanUp } = registerHelpers(getService); - // Failing: See https://github.com/elastic/kibana/issues/184128 - describe.skip('search', () => { + describe('search', () => { + after(() => cleanUp()); + const URI = `${API_BASE_PATH}/search`; it('return a 404 if the rollup index does not exist', async () => { @@ -32,8 +33,12 @@ export default function ({ getService }) { }); it('should return a 200 when searching on existing rollup index', async () => { + // From 8.15, Es only allows creating a new rollup job when there is existing rollup usage in the cluster + // We will simulate rollup usage by creating a mock-up rollup index + await createMockRollupIndex(); + // Create a Rollup job on an index with the INDEX_TO_ROLLUP_MAPPINGS - const indexName = await createIndexWithMappings(); + const indexName = await createIndexWithMappings(undefined, INDEX_TO_ROLLUP_MAPPINGS); const rollupIndex = getRandomString(); await createJob(getJobPayload(indexName, undefined, rollupIndex));