Skip to content

Commit

Permalink
Merge pull request #9 from PagerDuty/feat/add-support-for-event-grouping
Browse files Browse the repository at this point in the history
feat: add support for alert grouping
  • Loading branch information
t1agob authored Jan 3, 2024
2 parents 5bf08b6 + c606f2b commit a26bcac
Show file tree
Hide file tree
Showing 4 changed files with 345 additions and 26 deletions.
16 changes: 12 additions & 4 deletions src/actions/custom.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
import { z } from 'zod';
import * as api from '../apis/pagerduty';
import { CreateServiceResponse } from '../types';

export const createPagerDutyServiceAction = () => {

return createTemplateAction<{
name: string;
description: string;
escalationPolicyId: string;
alertGrouping?: string;
}>({
id: 'pagerduty:service:create',
schema: {
input: z.object({
name: z.string().min(1, "name is required").describe('Name of the service'),
description: z.string().min(1, "description is required").describe('Description of the service'),
escalationPolicyId: z.string().min(1, "Escalation policy is required").describe('Escalation policy ID'),
alertGrouping: z.string().optional().describe('Alert grouping parameters'),
}),
output: z.object({
serviceUrl: z.string().describe('PagerDuty Service URL'),
Expand All @@ -26,15 +29,20 @@ export const createPagerDutyServiceAction = () => {
async handler(ctx) {
try {
// Create service in PagerDuty
const [serviceId, serviceUrl] = await api.createService(ctx.input.name, ctx.input.description, ctx.input.escalationPolicyId);
const service: CreateServiceResponse = await api.createService(
ctx.input.name,
ctx.input.description,
ctx.input.escalationPolicyId,
ctx.input.alertGrouping);
ctx.logger.info(`Service '${ctx.input.name}' created successfully!`);
ctx.logger.info(`Alert grouping set to '${service.alertGrouping}'`);

ctx.output('serviceUrl', serviceUrl);
ctx.output('serviceId', serviceId);
ctx.output('serviceUrl', service.url);
ctx.output('serviceId', service.id);

// Create Backstage Integration in PagerDuty service
const backstageIntegrationId = 'PRO19CT'; // ID for Backstage integration
const integrationKey = await api.createServiceIntegration(serviceId, backstageIntegrationId);
const integrationKey = await api.createServiceIntegration(service.id, backstageIntegrationId);
ctx.logger.info(`Backstage Integration for service '${ctx.input.name}' created successfully!`);

ctx.output('integrationKey', integrationKey);
Expand Down
171 changes: 162 additions & 9 deletions src/apis/pagerduty.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,133 @@ describe("PagerDuty API", () => {
});

describe("createService", () => {
it("should create a service without event grouping when AIOps is not available", async () => {
const name = "TestService";
const description = "Test Service Description";
const escalationPolicyId = "12345";

const expectedResponse = { "alertGrouping": "null", "id": "S3RV1CE1D", "url": "https://testaccount.pagerduty.com/services/S3RV1CE1D" };

global.fetch = jest.fn().mockReturnValueOnce(
Promise.resolve({
status: 200,
json: () => Promise.resolve({
abilities: [
]
})
})
).mockReturnValueOnce(
Promise.resolve({
status: 201,
json: () => Promise.resolve({
service: {
id: "S3RV1CE1D",
htmlUrl: "https://testaccount.pagerduty.com/services/S3RV1CE1D",
}
})
})
) as jest.Mock;

const result = await createService(name, description, escalationPolicyId, "intelligent");

expect(result).toEqual(expectedResponse);
expect(fetch).toHaveBeenCalledTimes(2);
});

it("should create a service without event grouping when grouping is 'null'", async () => {
const name = "TestService";
const description = "Test Service Description";
const escalationPolicyId = "12345";

const expectedResponse = { "alertGrouping": "null", "id": "S3RV1CE1D", "url": "https://testaccount.pagerduty.com/services/S3RV1CE1D" };

global.fetch = jest.fn().mockReturnValueOnce(
Promise.resolve({
status: 200,
json: () => Promise.resolve({
abilities: [
"preview_intelligent_alert_grouping",
"time_based_alert_grouping"
]
})
})
).mockReturnValueOnce(
Promise.resolve({
status: 201,
json: () => Promise.resolve({
service: {
id: "S3RV1CE1D",
htmlUrl: "https://testaccount.pagerduty.com/services/S3RV1CE1D",
}
})
})
) as jest.Mock;

const result = await createService(name, description, escalationPolicyId, "null");

expect(result).toEqual(expectedResponse);
expect(fetch).toHaveBeenCalledTimes(2);
});

it("should create a service without event grouping when grouping is undefined", async () => {
const name = "TestService";
const description = "Test Service Description";
const escalationPolicyId = "12345";

const expectedResponse = { "alertGrouping": "null", "id": "S3RV1CE1D", "url": "https://testaccount.pagerduty.com/services/S3RV1CE1D" };

global.fetch = jest.fn().mockReturnValueOnce(
Promise.resolve({
status: 200,
json: () => Promise.resolve({
abilities: [
"preview_intelligent_alert_grouping",
"time_based_alert_grouping"
]
})
})
).mockReturnValueOnce(
Promise.resolve({
status: 201,
json: () => Promise.resolve({
service: {
id: "S3RV1CE1D",
htmlUrl: "https://testaccount.pagerduty.com/services/S3RV1CE1D",
}
})
})
) as jest.Mock;

const result = await createService(name, description, escalationPolicyId);

expect(result).toEqual(expectedResponse);
expect(fetch).toHaveBeenCalledTimes(2);
});

it("should create a service", async () => {
const name = "TestService";
const description = "Test Service Description";
const escalationPolicyId = "12345";

const expectedResponse = ["S3RV1CE1D", "https://testaccount.pagerduty.com/services/S3RV1CE1D"];
const expectedResponse = { "alertGrouping": "null", "id": "S3RV1CE1D", "url": "https://testaccount.pagerduty.com/services/S3RV1CE1D" };

global.fetch = jest.fn(() =>
global.fetch = jest.fn().mockReturnValueOnce(
Promise.resolve({
status: 200,
json: () => Promise.resolve({
abilities: [
"preview_intelligent_alert_grouping",
"time_based_alert_grouping"
]
})
})
).mockReturnValueOnce(
Promise.resolve({
status: 201,
json: () => Promise.resolve({
service: {
id: expectedResponse[0],
htmlUrl: expectedResponse[1],
id: "S3RV1CE1D",
htmlUrl: "https://testaccount.pagerduty.com/services/S3RV1CE1D",
}
})
})
Expand All @@ -30,15 +143,25 @@ describe("PagerDuty API", () => {
const result = await createService(name, description, escalationPolicyId);

expect(result).toEqual(expectedResponse);
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledTimes(2);
});

it("should NOT create a service when caller provides invalid arguments", async () => {
const name = "TestService";
const description = "Test Service Description";
const escalationPolicyId = "";

global.fetch = jest.fn(() =>
global.fetch = jest.fn().mockReturnValueOnce(
Promise.resolve({
status: 200,
json: () => Promise.resolve({
abilities: [
"preview_intelligent_alert_grouping",
"time_based_alert_grouping"
]
})
})
).mockReturnValueOnce(
Promise.resolve({
status: 400,
json: () => Promise.resolve({})
Expand All @@ -57,7 +180,17 @@ describe("PagerDuty API", () => {
const description = "Test Service Description";
const escalationPolicyId = "";

global.fetch = jest.fn(() =>
global.fetch = jest.fn().mockReturnValueOnce(
Promise.resolve({
status: 200,
json: () => Promise.resolve({
abilities: [
"preview_intelligent_alert_grouping",
"time_based_alert_grouping"
]
})
})
).mockReturnValueOnce(
Promise.resolve({
status: 401,
json: () => Promise.resolve({})
Expand All @@ -76,7 +209,17 @@ describe("PagerDuty API", () => {
const description = "Test Service Description";
const escalationPolicyId = "12345";

global.fetch = jest.fn(() =>
global.fetch = jest.fn().mockReturnValueOnce(
Promise.resolve({
status: 200,
json: () => Promise.resolve({
abilities: [
"preview_intelligent_alert_grouping",
"time_based_alert_grouping"
]
})
})
).mockReturnValueOnce(
Promise.resolve({
status: 402,
json: () => Promise.resolve({})
Expand All @@ -95,7 +238,17 @@ describe("PagerDuty API", () => {
const description = "Test Service Description";
const escalationPolicyId = "12345";

global.fetch = jest.fn(() =>
global.fetch = jest.fn().mockReturnValueOnce(
Promise.resolve({
status: 200,
json: () => Promise.resolve({
abilities: [
"preview_intelligent_alert_grouping",
"time_based_alert_grouping"
]
})
})
).mockReturnValueOnce(
Promise.resolve({
status: 403,
json: () => Promise.resolve({})
Expand Down
Loading

0 comments on commit a26bcac

Please sign in to comment.