Fixing pagerduty server side functionality (#101091)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
ymao1 2021-06-03 09:35:27 -04:00 committed by GitHub
parent f5df40a5a1
commit b8c127c18f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 213 additions and 10 deletions

View file

@ -152,14 +152,15 @@ describe('validateParams()', () => {
`);
});
test('should validate and throw error when timestamp has spaces', () => {
test('should validate and pass when valid timestamp has spaces', () => {
const randoDate = new Date('1963-09-23T01:23:45Z').toISOString();
const timestamp = ` ${randoDate}`;
expect(() => {
validateParams(actionType, {
timestamp,
});
}).toThrowError(`error validating action params: error parsing timestamp "${timestamp}"`);
expect(validateParams(actionType, { timestamp })).toEqual({ timestamp });
});
test('should validate and pass when timestamp is empty string', () => {
const timestamp = '';
expect(validateParams(actionType, { timestamp })).toEqual({ timestamp });
});
test('should validate and throw error when timestamp is invalid', () => {
@ -409,7 +410,7 @@ describe('execute()', () => {
`);
});
test('should fail when sendPagerdury throws', async () => {
test('should fail when sendPagerduty throws', async () => {
const secrets = { routingKey: 'super-secret' };
const config = { apiUrl: null };
const params = {};
@ -576,4 +577,195 @@ describe('execute()', () => {
}
`);
});
test('should succeed when timestamp contains valid date and extraneous spaces', async () => {
const randoDate = new Date('1963-09-23T01:23:45Z').toISOString();
const secrets = {
routingKey: 'super-secret',
};
const config = {
apiUrl: 'the-api-url',
};
const params: ActionParamsType = {
eventAction: 'trigger',
dedupKey: 'a-dedup-key',
summary: 'the summary',
source: 'the-source',
severity: 'critical',
timestamp: ` ${randoDate} `,
component: 'the-component',
group: 'the-group',
class: 'the-class',
};
postPagerdutyMock.mockImplementation(() => {
return { status: 202, data: 'data-here' };
});
const actionId = 'some-action-id';
const executorOptions: PagerDutyActionTypeExecutorOptions = {
actionId,
config,
params,
secrets,
services,
};
const actionResponse = await actionType.executor(executorOptions);
const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0];
expect({ apiUrl, data, headers }).toMatchInlineSnapshot(`
Object {
"apiUrl": "the-api-url",
"data": Object {
"dedup_key": "a-dedup-key",
"event_action": "trigger",
"payload": Object {
"class": "the-class",
"component": "the-component",
"group": "the-group",
"severity": "critical",
"source": "the-source",
"summary": "the summary",
"timestamp": "1963-09-23T01:23:45.000Z",
},
},
"headers": Object {
"Content-Type": "application/json",
"X-Routing-Key": "super-secret",
},
}
`);
expect(actionResponse).toMatchInlineSnapshot(`
Object {
"actionId": "some-action-id",
"data": "data-here",
"status": "ok",
}
`);
});
test('should not pass timestamp field when timestamp is empty string', async () => {
const secrets = {
routingKey: 'super-secret',
};
const config = {
apiUrl: 'the-api-url',
};
const params: ActionParamsType = {
eventAction: 'trigger',
dedupKey: 'a-dedup-key',
summary: 'the summary',
source: 'the-source',
severity: 'critical',
timestamp: '',
component: 'the-component',
group: 'the-group',
class: 'the-class',
};
postPagerdutyMock.mockImplementation(() => {
return { status: 202, data: 'data-here' };
});
const actionId = 'some-action-id';
const executorOptions: PagerDutyActionTypeExecutorOptions = {
actionId,
config,
params,
secrets,
services,
};
const actionResponse = await actionType.executor(executorOptions);
const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0];
expect({ apiUrl, data, headers }).toMatchInlineSnapshot(`
Object {
"apiUrl": "the-api-url",
"data": Object {
"dedup_key": "a-dedup-key",
"event_action": "trigger",
"payload": Object {
"class": "the-class",
"component": "the-component",
"group": "the-group",
"severity": "critical",
"source": "the-source",
"summary": "the summary",
},
},
"headers": Object {
"Content-Type": "application/json",
"X-Routing-Key": "super-secret",
},
}
`);
expect(actionResponse).toMatchInlineSnapshot(`
Object {
"actionId": "some-action-id",
"data": "data-here",
"status": "ok",
}
`);
});
test('should not pass timestamp field when timestamp is string of spaces', async () => {
const secrets = {
routingKey: 'super-secret',
};
const config = {
apiUrl: 'the-api-url',
};
const params: ActionParamsType = {
eventAction: 'trigger',
dedupKey: 'a-dedup-key',
summary: 'the summary',
source: 'the-source',
severity: 'critical',
timestamp: ' ',
component: 'the-component',
group: 'the-group',
class: 'the-class',
};
postPagerdutyMock.mockImplementation(() => {
return { status: 202, data: 'data-here' };
});
const actionId = 'some-action-id';
const executorOptions: PagerDutyActionTypeExecutorOptions = {
actionId,
config,
params,
secrets,
services,
};
const actionResponse = await actionType.executor(executorOptions);
const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0];
expect({ apiUrl, data, headers }).toMatchInlineSnapshot(`
Object {
"apiUrl": "the-api-url",
"data": Object {
"dedup_key": "a-dedup-key",
"event_action": "trigger",
"payload": Object {
"class": "the-class",
"component": "the-component",
"group": "the-group",
"severity": "critical",
"source": "the-source",
"summary": "the summary",
},
},
"headers": Object {
"Content-Type": "application/json",
"X-Routing-Key": "super-secret",
},
}
`);
expect(actionResponse).toMatchInlineSnapshot(`
Object {
"actionId": "some-action-id",
"data": "data-here",
"status": "ok",
}
`);
});
});

View file

@ -85,11 +85,19 @@ const ParamsSchema = schema.object(
{ validate: validateParams }
);
function validateTimestamp(timestamp?: string): string | null {
if (timestamp) {
return timestamp.trim().length > 0 ? timestamp.trim() : null;
}
return null;
}
function validateParams(paramsObject: unknown): string | void {
const { timestamp, eventAction, dedupKey } = paramsObject as ActionParamsType;
if (timestamp != null) {
const validatedTimestamp = validateTimestamp(timestamp);
if (validatedTimestamp != null) {
try {
const date = Date.parse(timestamp);
const date = Date.parse(validatedTimestamp);
if (isNaN(date)) {
return i18n.translate('xpack.actions.builtin.pagerduty.invalidTimestampErrorMessage', {
defaultMessage: `error parsing timestamp "{timestamp}"`,
@ -279,11 +287,14 @@ function getBodyForEventAction(actionId: string, params: ActionParamsType): Page
return data;
}
const validatedTimestamp = validateTimestamp(params.timestamp);
data.payload = {
summary: params.summary || 'No summary provided.',
source: params.source || `Kibana Action ${actionId}`,
severity: params.severity || 'info',
...omitBy(pick(params, ['timestamp', 'component', 'group', 'class']), isUndefined),
...(validatedTimestamp ? { timestamp: validatedTimestamp } : {}),
...omitBy(pick(params, ['component', 'group', 'class']), isUndefined),
};
return data;