Skip to content

Commit

Permalink
ExecutionContext: encode all context fields when converting to header (
Browse files Browse the repository at this point in the history
…#125783) (#125925)

* ExecutionContext: encode all context fields when converting to header value

* switch back to using the vis type name instead of title for the execution context name

* adapt FTR tests

* fix server-side tests too

(cherry picked from commit d047765)

Co-authored-by: Pierre Gayvallet <pierre.gayvallet@elastic.co>
  • Loading branch information
kibanamachine and pgayvallet authored Feb 17, 2022
1 parent f41c1b4 commit 1fd2f21
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,40 @@ describe('KibanaExecutionContext', () => {
expect(value).toBe('type:name:41;child-test-type:child-test-name:42');
});

it('returns an escaped string representation of provided execution contextStringified', () => {
it('returns an escaped string representation of provided execution context', () => {
const context: KibanaExecutionContext = {
id: 'Visualization☺漢字',
type: 'test☺type',
name: 'test漢name',
description: 'test字description',
};

const value = new ExecutionContextContainer(context).toString();
expect(value).toBe(
'test%E2%98%BAtype:test%E6%BC%A2name:Visualization%E2%98%BA%E6%BC%A2%E5%AD%97'
);
});

it('returns an escaped string representation of provided execution context parent', () => {
const parentContext: KibanaExecutionContext = {
id: 'Dashboard☺漢字',
type: 'test☺type',
name: 'test漢name',
description: 'parent-descripton',
};
const parentContainer = new ExecutionContextContainer(parentContext);

const context: KibanaExecutionContext = {
id: 'Visualization',
type: 'test-type',
name: 'test-name',
description: 'test-description',
};

const value = new ExecutionContextContainer(context).toString();
expect(value).toBe('test-type:test-name:Visualization%E2%98%BA%E6%BC%A2%E5%AD%97');
const value = new ExecutionContextContainer(context, parentContainer).toString();
expect(value).toBe(
'test%E2%98%BAtype:test%E6%BC%A2name:Dashboard%E2%98%BA%E6%BC%A2%E5%AD%97;test-type:test-name:Visualization'
);
});

it('trims a string representation of provided execution context if it is bigger max allowed size', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,23 @@ export interface IExecutionContextContainer {
}

function stringify(ctx: KibanaExecutionContext): string {
const stringifiedCtx = `${ctx.type}:${ctx.name}:${encodeURIComponent(ctx.id!)}`;
const stringifiedCtx = `${encodeURIComponent(ctx.type)}:${encodeURIComponent(
ctx.name
)}:${encodeURIComponent(ctx.id!)}`;
return ctx.child ? `${stringifiedCtx};${stringify(ctx.child)}` : stringifiedCtx;
}

export class ExecutionContextContainer implements IExecutionContextContainer {
readonly #context: Readonly<KibanaExecutionContext>;

constructor(context: KibanaExecutionContext, parent?: IExecutionContextContainer) {
this.#context = parent ? { ...parent.toJSON(), child: context } : context;
}

toString(): string {
return enforceMaxLength(stringify(this.#context));
}

toJSON() {
return this.#context;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ const parentContext = {
description: 'test-description',
};

const withUtf8CharsContext = {
type: 'test字type',
name: 'test漢字name',
id: '9000☺',
description: 'test-description',
};

describe('trace', () => {
let esServer: kbnTestServer.TestElasticsearchUtils;
let root: ReturnType<typeof kbnTestServer.createRoot>;
Expand Down Expand Up @@ -362,6 +369,35 @@ describe('trace', () => {
expect(response.body).toEqual(parentContext);
});

it('supports UTF-8 characters', async () => {
const { http } = await root.setup();
const { createRouter } = http;

const router = createRouter('');
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
{},
{ meta: true }
);
return res.ok({ body: headers || {} });
});

await root.start();
const response = await kbnTestServer.request
.get(root, '/execution-context')
.set('x-opaque-id', 'utf-test')
.set(new ExecutionContextContainer(withUtf8CharsContext).toHeader())
.expect(200);

const rawOpaqueId = response.body['x-opaque-id'];
expect(rawOpaqueId).toEqual(
'utf-test;kibana:test%E5%AD%97type:test%E6%BC%A2%E5%AD%97name:9000%E2%98%BA'
);
expect(decodeURIComponent(rawOpaqueId)).toEqual(
'utf-test;kibana:test字type:test漢字name:9000☺'
);
});

it('execution context is the same for all the lifecycle events', async () => {
const { executionContext, http } = await root.setup();
const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ export class VisualizeEmbeddable
const parentContext = this.parent?.getInput().executionContext;
const child: KibanaExecutionContext = {
type: 'visualization',
name: this.vis.type.title,
name: this.vis.type.name,
id: this.vis.id ?? 'an_unsaved_vis',
description: this.vis.title || this.input.title || this.vis.type.name,
url: this.output.editUrl,
Expand Down
17 changes: 9 additions & 8 deletions x-pack/test/functional_execution_context/tests/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
predicate: (record) =>
Boolean(
record.http?.request?.id?.includes(
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:TSVB:bcb63b50-4c89-11e8-b3d7-01146121b73d'
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:metrics:bcb63b50-4c89-11e8-b3d7-01146121b73d'
)
),
retry,
Expand All @@ -269,7 +269,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
child: {
type: 'visualization',
name: 'TSVB',
name: 'metrics',
id: 'bcb63b50-4c89-11e8-b3d7-01146121b73d',
description: '[Flights] Delays & Cancellations',
url: '/app/visualize#/edit/bcb63b50-4c89-11e8-b3d7-01146121b73d',
Expand All @@ -279,13 +279,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
});

// application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b
it('propagates context for Vega visualizations', async () => {
await assertLogContains({
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
predicate: (record) =>
Boolean(
record.http?.request?.id?.includes(
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:Vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b'
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b'
)
),
retry,
Expand All @@ -302,7 +303,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
child: {
type: 'visualization',
name: 'Vega',
name: 'vega',
id: 'ed78a660-53a0-11e8-acbd-0be0ad9d822b',
description: '[Flights] Airport Connections (Hover Over Airport)',
url: '/app/visualize#/edit/ed78a660-53a0-11e8-acbd-0be0ad9d822b',
Expand All @@ -318,7 +319,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
predicate: (record) =>
Boolean(
record.http?.request?.id?.includes(
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:Tag cloud:293b5a30-4c8f-11e8-b3d7-01146121b73d'
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:tagcloud:293b5a30-4c8f-11e8-b3d7-01146121b73d'
)
),
retry,
Expand All @@ -335,7 +336,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
child: {
type: 'visualization',
name: 'Tag cloud',
name: 'tagcloud',
id: '293b5a30-4c8f-11e8-b3d7-01146121b73d',
description: '[Flights] Destination Weather',
url: '/app/visualize#/edit/293b5a30-4c8f-11e8-b3d7-01146121b73d',
Expand All @@ -351,7 +352,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
predicate: (record) =>
Boolean(
record.http?.request?.id?.includes(
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:Vertical bar:9886b410-4c8b-11e8-b3d7-01146121b73d'
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:histogram:9886b410-4c8b-11e8-b3d7-01146121b73d'
)
),
retry,
Expand All @@ -368,7 +369,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
child: {
type: 'visualization',
name: 'Vertical bar',
name: 'histogram',
id: '9886b410-4c8b-11e8-b3d7-01146121b73d',
description: '[Flights] Delay Buckets',
url: '/app/visualize#/edit/9886b410-4c8b-11e8-b3d7-01146121b73d',
Expand Down
4 changes: 2 additions & 2 deletions x-pack/test/functional_execution_context/tests/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default function ({ getService }: FtrProviderContext) {
Boolean(
// exclude part with taskId
record.http?.request?.id?.includes(
`kibana:task manager:run alerting:test.executionContext:`
`kibana:task%20manager:run%20alerting%3Atest.executionContext:`
)
),
retry,
Expand All @@ -84,7 +84,7 @@ export default function ({ getService }: FtrProviderContext) {
'alerting execution context propagates to Elasticsearch via "x-opaque-id" header',
predicate: (record) =>
Boolean(
record.http?.request?.id?.includes(`alert:execute test.executionContext:${alertId}`)
record.http?.request?.id?.includes(`alert:execute%20test.executionContext:${alertId}`)
),
retry,
});
Expand Down

0 comments on commit 1fd2f21

Please sign in to comment.