Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export interface ReportSource {
*/
kibana_name?: string; // for troubleshooting
kibana_id?: string; // for troubleshooting
space_id?: string;
timeout?: number; // for troubleshooting: the actual comparison uses the config setting xpack.reporting.queue.timeout
max_attempts?: number; // for troubleshooting: the actual comparison uses the config setting xpack.reporting.capture.maxAttempts
started_at?: string; // timestamp in UTC
Expand Down
2 changes: 1 addition & 1 deletion x-pack/platform/plugins/private/reporting/server/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ export class ReportingCore {
const spaceId = spacesService?.getSpaceId(request);

if (spaceId !== DEFAULT_SPACE_ID) {
logger.info(`Request uses Space ID: ${spaceId}`);
logger.debug(`Request uses Space ID: ${spaceId}`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this is info level. It gets logged every time the Reporting UI is accessed in a different space and there is auto-refresh enabled on that page so it gets logged a lot 🙈

return spaceId;
} else {
logger.debug(`Request uses default Space`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('Class Report', () => {
version: '7.14.0',
browserTimezone: 'UTC',
},
space_id: 'a_space',
meta: { objectType: 'test' },
timeout: 30000,
});
Expand All @@ -36,6 +37,7 @@ describe('Class Report', () => {
started_at: undefined,
status: 'pending',
timeout: 30000,
space_id: 'a_space',
});
expect(report.toReportTaskJSON()).toMatchObject({
attempts: 0,
Expand All @@ -55,6 +57,7 @@ describe('Class Report', () => {
meta: { objectType: 'test' },
status: 'pending',
timeout: 30000,
space_id: 'a_space',
});

expect(report._id).toBeDefined();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class Report implements Partial<ReportSource & ReportDocumentHead> {
public readonly created_at: ReportSource['created_at'];
public readonly created_by: ReportSource['created_by'];
public readonly payload: ReportSource['payload'];
public readonly space_id: ReportSource['space_id'];

public readonly meta: ReportSource['meta'];

Expand Down Expand Up @@ -81,6 +82,7 @@ export class Report implements Partial<ReportSource & ReportDocumentHead> {
this.payload = opts.payload;
this.kibana_id = opts.kibana_id;
this.kibana_name = opts.kibana_name;
this.space_id = opts.space_id;
this.jobtype = opts.jobtype;
this.max_attempts = opts.max_attempts;
this.attempts = opts.attempts || 0;
Expand Down Expand Up @@ -137,6 +139,7 @@ export class Report implements Partial<ReportSource & ReportDocumentHead> {
started_at: this.started_at,
completed_at: this.completed_at,
process_expiration: this.process_expiration,
space_id: this.space_id,
output: this.output || null,
metrics: this.metrics,
};
Expand Down Expand Up @@ -184,6 +187,7 @@ export class Report implements Partial<ReportSource & ReportDocumentHead> {
queue_time_ms: this.queue_time_ms?.[0],
execution_time_ms: this.execution_time_ms?.[0],
migration_version: this.migration_version,
space_id: this.space_id,
payload: omit(this.payload, 'headers'),
output: omit(this.output, 'content'),
metrics: this.metrics,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ describe('ReportingStore', () => {
},
"process_expiration": undefined,
"queue_time_ms": undefined,
"space_id": undefined,
"started_at": undefined,
"status": "pending",
"timeout": 30000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ describe('Handle request to generate', () => {
"output": null,
"process_expiration": undefined,
"queue_time_ms": undefined,
"space_id": "default",
"started_at": undefined,
"status": "pending",
"timeout": undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { BaseParams } from '@kbn/reporting-common/types';
import { cryptoFactory } from '@kbn/reporting-server';
import rison from '@kbn/rison';

import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import { type Counters, getCounters } from '..';
import type { ReportingCore } from '../../..';
import { checkParamsVersion } from '../../../lib';
Expand Down Expand Up @@ -85,14 +86,16 @@ export class RequestHandler {
// 3. Create a payload object by calling exportType.createJob(), and adding some automatic parameters
const job = await exportType.createJob(jobParams, context, req);

const spaceId = reporting.getSpaceId(req, logger);

const payload = {
...job,
headers,
title: job.title,
objectType: jobParams.objectType,
browserTimezone: jobParams.browserTimezone,
version: jobParams.version,
spaceId: reporting.getSpaceId(req, logger),
spaceId,
};

// 4. Add the report to ReportingStore to show as pending
Expand All @@ -102,6 +105,7 @@ export class RequestHandler {
created_by: user ? user.username : false,
payload,
migration_version: jobParams.version,
space_id: spaceId || DEFAULT_SPACE_ID,
meta: {
// telemetry fields
objectType: jobParams.objectType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,20 @@

import { set } from '@kbn/safer-lodash-set';

import { ElasticsearchClient } from '@kbn/core/server';
import { ElasticsearchClient, KibanaRequest } from '@kbn/core/server';
import { elasticsearchServiceMock } from '@kbn/core/server/mocks';
import { JOB_STATUS } from '@kbn/reporting-common';
import { createMockConfigSchema } from '@kbn/reporting-mocks-server';
import { createMockReportingCore } from '../../../test_helpers';
import { jobsQueryFactory } from './jobs_query';

const fakeRawRequest = {
headers: {
authorization: `ApiKey skdjtq4u543yt3rhewrh`,
},
path: '/',
} as unknown as KibanaRequest;

describe('jobsQuery', () => {
let client: ReturnType<typeof elasticsearchServiceMock.createElasticsearchClient>;
let jobsQuery: ReturnType<typeof jobsQueryFactory>;
Expand All @@ -37,10 +44,11 @@ describe('jobsQuery', () => {
});

it('should pass parameters in the request body', async () => {
await jobsQuery.list({ username: 'somebody' }, 1, 10, ['id1', 'id2']);
await jobsQuery.list({ username: 'somebody' }, 1, 10, null);
await jobsQuery.list(fakeRawRequest, { username: 'somebody' }, 1, 10, ['id1', 'id2']);
await jobsQuery.list(fakeRawRequest, { username: 'somebody' }, 1, 10, null);

expect(client.search).toHaveBeenCalledTimes(2);

expect(client.search).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
Expand All @@ -52,6 +60,15 @@ describe('jobsQuery', () => {
expect.arrayContaining([
{ term: { created_by: 'somebody' } },
{ ids: { values: ['id1', 'id2'] } },
{
bool: {
should: [
{ term: { space_id: 'default' } },
// also show all reports created before space_id was added
{ bool: { must_not: { exists: { field: 'space_id' } } } },
],
},
},
])
),
})
Expand All @@ -70,7 +87,9 @@ describe('jobsQuery', () => {
});

it('should return reports list', async () => {
await expect(jobsQuery.list({ username: 'somebody' }, 0, 10, [])).resolves.toEqual(
await expect(
jobsQuery.list(fakeRawRequest, { username: 'somebody' }, 0, 10, [])
).resolves.toEqual(
expect.arrayContaining([
expect.objectContaining({ id: 'id1', jobtype: 'pdf' }),
expect.objectContaining({ id: 'id2', jobtype: 'csv' }),
Expand All @@ -81,17 +100,19 @@ describe('jobsQuery', () => {
it('should return an empty array when there are no hits', async () => {
client.search.mockResponse({} as Awaited<ReturnType<ElasticsearchClient['search']>>);

await expect(jobsQuery.list({ username: 'somebody' }, 0, 10, [])).resolves.toHaveLength(0);
await expect(
jobsQuery.list(fakeRawRequest, { username: 'somebody' }, 0, 10, [])
).resolves.toHaveLength(0);
});

it('should reject if the report source is missing', async () => {
client.search.mockResponse(
set<Awaited<ReturnType<ElasticsearchClient['search']>>>({}, 'hits.hits', [{}])
);

await expect(jobsQuery.list({ username: 'somebody' }, 0, 10, [])).rejects.toBeInstanceOf(
Error
);
await expect(
jobsQuery.list(fakeRawRequest, { username: 'somebody' }, 0, 10, [])
).rejects.toBeInstanceOf(Error);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
*/

import { TransportResult, errors, estypes } from '@elastic/elasticsearch';
import type { ElasticsearchClient } from '@kbn/core/server';
import type { ElasticsearchClient, KibanaRequest } from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
import { JOB_STATUS } from '@kbn/reporting-common';
import type { ReportApiJSON, ReportSource } from '@kbn/reporting-common/types';
import { REPORTING_DATA_STREAM_WILDCARD_WITH_LEGACY } from '@kbn/reporting-server';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import type { ReportingCore } from '../../..';
import { Report } from '../../../lib/store';
import { runtimeFieldKeys, runtimeFields } from '../../../lib/store/runtime_fields';
Expand Down Expand Up @@ -40,6 +41,7 @@ export type ReportContent = Pick<ReportSource, 'status' | 'jobtype' | 'output'>

export interface JobsQueryFactory {
list(
req: KibanaRequest,
user: ReportingUser,
page: number,
size: number,
Expand Down Expand Up @@ -73,8 +75,9 @@ export function jobsQueryFactory(
}

return {
async list(user, page = 0, size = defaultSize, jobIds) {
async list(req, user, page = 0, size = defaultSize, jobIds) {
const username = getUsername(user);
const spaceId = reportingCore.getSpaceId(req) || DEFAULT_SPACE_ID;
const body = getSearchBody({
size,
from: size * page,
Expand All @@ -85,6 +88,15 @@ export function jobsQueryFactory(
must: [
{ term: { created_by: username } },
...(jobIds ? [{ ids: { values: jobIds } }] : []),
{
bool: {
should: [
{ term: { space_id: spaceId } },
// also show all reports created before space_id was added
{ bool: { must_not: { exists: { field: 'space_id' } } } },
],
},
},
],
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function registerJobInfoRoutesInternal(reporting: ReportingCore) {
const page = parseInt(queryPage, 10) || 0;
const size = Math.min(100, parseInt(querySize, 10) || 10);
const jobIds = queryIds ? queryIds.split(',') : null;
const results = await jobsQuery.list(user, page, size, jobIds);
const results = await jobsQuery.list(req, user, page, size, jobIds);

counters.usageCounter();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./ilm_migration_apis'));
loadTestFile(require.resolve('./security_roles_privileges'));
loadTestFile(require.resolve('./spaces'));
loadTestFile(require.resolve('./list_jobs'));

// CSV-specific
loadTestFile(require.resolve('./csv/csv_v2'));
Expand Down
Loading