Skip to content

Commit

Permalink
refactor: refactor code for retro-compatibility
Browse files Browse the repository at this point in the history
refactored the code to support both backend systems with minor changes for existing users

Signed-off-by: Tiago Barbosa <tbarbos@hotmail.com>
  • Loading branch information
t1agob committed Apr 12, 2024
1 parent d842e4b commit 9bcfb29
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 40 deletions.
9 changes: 0 additions & 9 deletions dev/index.ts

This file was deleted.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"types": "dist/index.d.ts"
},
"backstage": {
"role": "backend-plugin"
"role": "backend-plugin-module"
},
"scripts": {
"start": "yarn tsc && backstage-cli package start",
Expand All @@ -22,8 +22,10 @@
"postpack": "backstage-cli package postpack"
},
"dependencies": {
"@backstage/backend-common": "^0.21.6",
"@backstage/backend-defaults": "^0.2.16",
"@backstage/backend-plugin-api": "^0.6.16",
"@backstage/config": "^1.2.0",
"@backstage/plugin-scaffolder-node": "^0.4.2",
"@rjsf/core": "^5.14.3",
"node-fetch": "^2.6.7",
Expand Down
38 changes: 32 additions & 6 deletions src/actions/custom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@ import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
import { z } from 'zod';
import * as api from '../apis/pagerduty';
import { CreateServiceResponse } from '../types';
import { loadAuthConfig } from '../auth/auth';
import { LoggerService, RootConfigService } from '@backstage/backend-plugin-api';
import { Config } from "@backstage/config";
import { loadBackendConfig } from "@backstage/backend-common";

export const createPagerDutyServiceAction = () => {
export type CreatePagerDutyServiceActionProps = {
config: RootConfigService;
logger: LoggerService;
};

export const createPagerDutyServiceAction = (props : CreatePagerDutyServiceActionProps) => {

let loggerService: LoggerService;

return createTemplateAction<{
name: string;
Expand All @@ -27,27 +38,42 @@ export const createPagerDutyServiceAction = () => {
},

async handler(ctx) {
try {
try {
loggerService = props?.logger ? props.logger : ctx.logger;
const configService = props?.config ?? props.config;

const legacyConfig: Config = await loadBackendConfig({
logger: loggerService,
argv: [],
});

// Load the auth configuration
await loadAuthConfig({
config: configService,
legacyConfig: legacyConfig,
logger: loggerService,
});

// Create service in PagerDuty
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}'`);
loggerService.info(`Service '${ctx.input.name}' created successfully!`);
loggerService.info(`Alert grouping set to '${service.alertGrouping}'`);

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(service.id, backstageIntegrationId);
ctx.logger.info(`Backstage Integration for service '${ctx.input.name}' created successfully!`);
loggerService.info(`Backstage Integration for service '${ctx.input.name}' created successfully!`);

ctx.output('integrationKey', integrationKey);
} catch (error) {
ctx.logger.error(`${error}`);
loggerService.error(`${error}`);
}

}
Expand Down
86 changes: 67 additions & 19 deletions src/auth/auth.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,88 @@
import { LoggerService, RootConfigService } from "@backstage/backend-plugin-api";
import { HttpError } from "@pagerduty/backstage-plugin-common";
import { Config } from "@backstage/config";

type Auth = {
config: RootConfigService;
logger: LoggerService;
authToken: string;
authTokenExpiryDate: number;
}

export type LoadAuthConfigProps = {
config: RootConfigService;
legacyConfig: Config;
logger: LoggerService;
}

type JsonValue = boolean | number | string | null | JsonArray | JsonObject;

interface JsonObject {
[x: string]: JsonValue;
}

type JsonArray = JsonValue[];

let authPersistence: Auth;
let isLegacyConfig: boolean;
let _config: RootConfigService;
let _legacyConfig: Config;
let _logger: LoggerService;

export async function getAuthToken(): Promise<string> {
// check if token already exists and is valid
if (
(authPersistence.authToken !== '' &&
authPersistence.authToken.includes('Bearer') &&
(authPersistence?.authToken?.includes('Bearer') &&
authPersistence.authTokenExpiryDate > Date.now()) // case where OAuth token is still valid
||
(authPersistence.authToken !== '' &&
authPersistence.authToken.includes('Token'))) { // case where API token is used
(authPersistence?.authToken?.includes('Token'))) { // case where API token is used
return authPersistence.authToken;
}

await loadAuthConfig(authPersistence.config, authPersistence.logger);
await loadAuthConfig({
config: _config,
legacyConfig: _legacyConfig,
logger: _logger,
});
return authPersistence.authToken;
}

export async function loadAuthConfig(config : RootConfigService, logger: LoggerService) {
export async function loadAuthConfig({config, legacyConfig, logger}: LoadAuthConfigProps) {
try {
// check if we are using new backend system. Fallback to legacy config if not
isLegacyConfig = !config;

// set config and logger
_config = config;
_legacyConfig = legacyConfig;
_logger = logger;

// initiliaze the authPersistence in-memory object
authPersistence = {
config,
logger,
authToken: '',
authTokenExpiryDate: Date.now()
};

if (!config.getOptionalString('pagerDuty.apiToken')) {
if (!readOptionalString('pagerDuty.apiToken')) {
logger.warn('No PagerDuty API token found in config file. Trying OAuth token instead...');

if (!config.getOptional('pagerDuty.oauth')) {

if (!readOptionalObject('pagerDuty.oauth')) {
logger.error('No PagerDuty OAuth configuration found in config file.');

} else if (!config.getOptionalString('pagerDuty.oauth.clientId') || !config.getOptionalString('pagerDuty.oauth.clientSecret') || !config.getOptionalString('pagerDuty.oauth.subDomain')) {
} else if (!readOptionalString('pagerDuty.oauth.clientId') || !readOptionalString('pagerDuty.oauth.clientSecret') || !readOptionalString('pagerDuty.oauth.subDomain')) {

logger.error("Missing required PagerDuty OAuth parameters in config file. 'clientId', 'clientSecret', and 'subDomain' are required. 'region' is optional.");

} else {

authPersistence.authToken = await getOAuthToken(
config.getString('pagerDuty.oauth.clientId'),
config.getString('pagerDuty.oauth.clientSecret'),
config.getString('pagerDuty.oauth.subDomain'),
config.getOptionalString('pagerDuty.oauth.region') ?? 'us');
readString('pagerDuty.oauth.clientId'),
readString('pagerDuty.oauth.clientSecret'),
readString('pagerDuty.oauth.subDomain'),
readOptionalString('pagerDuty.oauth.region') ?? 'us');

logger.info('PagerDuty OAuth configuration loaded successfully.');
}
} else {
authPersistence.authToken = `Token token=${config.getString('pagerDuty.apiToken')}`;
authPersistence.authToken = `Token token=${readString('pagerDuty.apiToken')}`;

logger.info('PagerDuty API token loaded successfully.');
}
Expand All @@ -69,6 +92,31 @@ export async function loadAuthConfig(config : RootConfigService, logger: LoggerS
}
}

function readOptionalString(key: string) : string | undefined {
if (isLegacyConfig) {
return _legacyConfig.getOptionalString(key);
}

return _config.getOptionalString(key);
}

function readOptionalObject(key: string): JsonValue | undefined {
if (isLegacyConfig) {
return _legacyConfig.getOptional(key);
}

return _config.getOptional(key);
}

function readString(key: string) : string {
if (isLegacyConfig) {
return _legacyConfig.getString(key);
}

return _config.getString(key);
}


async function getOAuthToken(clientId: string, clientSecret: string, subDomain: string, region: string): Promise<string> {
// check if required parameters are provided
if (!clientId || !clientSecret || !subDomain) {
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { pagerDutyScaffolderActions as default } from './plugin';
export * from './actions/custom';
export { pagerDutyScaffolderActions as default } from './module';
export * from './actions/custom';
13 changes: 10 additions & 3 deletions src/plugin.ts → src/module.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { createBackendModule } from "@backstage/backend-plugin-api";
import { coreServices, createBackendModule } from "@backstage/backend-plugin-api";
import { scaffolderActionsExtensionPoint } from "@backstage/plugin-scaffolder-node/alpha";
import { createPagerDutyServiceAction } from "./actions/custom";


/** @public */
export const pagerDutyScaffolderActions = createBackendModule({
pluginId: 'scaffolder',
moduleId: 'custom-extensions',
register(env) {
env.registerInit({
deps: {
config: coreServices.rootConfig,
logger: coreServices.logger,
scaffolder: scaffolderActionsExtensionPoint,
},
async init({ scaffolder }) {
scaffolder.addActions(createPagerDutyServiceAction());
async init({ config, logger, scaffolder }) {

scaffolder.addActions(createPagerDutyServiceAction({
config,
logger
}));
},
});
},
Expand Down
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,11 @@ export type CreateServiceResponse = {
url: string;
alertGrouping: string;
};

import { Logger } from 'winston';
import { Config } from '@backstage/config';

export type PluginEnvironment = {
logger: Logger;
config: Config;
};
2 changes: 2 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4357,9 +4357,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "@pagerduty/backstage-plugin-scaffolder-actions@workspace:."
dependencies:
"@backstage/backend-common": ^0.21.6
"@backstage/backend-defaults": ^0.2.16
"@backstage/backend-plugin-api": ^0.6.16
"@backstage/cli": ^0.24.0
"@backstage/config": ^1.2.0
"@backstage/plugin-scaffolder-node": ^0.4.2
"@pagerduty/backstage-plugin-common": ^0.1.3
"@rjsf/core": ^5.14.3
Expand Down

0 comments on commit 9bcfb29

Please sign in to comment.