Skip to content

Commit a68b38d

Browse files
authored
feat: update Keycloak plugin for dynamic backend (#869)
Update Keycloak plugin for dynamic backend Add dynamic backend module capabilities for the Keycloak backend plugin. Signed-off-by: Craig Tracey <[email protected]>
1 parent 0c31158 commit a68b38d

File tree

6 files changed

+2844
-141
lines changed

6 files changed

+2844
-141
lines changed

plugins/keycloak-backend/package.json

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,22 @@
1111
"types": "dist/index.d.ts"
1212
},
1313
"backstage": {
14-
"role": "backend-plugin"
14+
"role": "backend-plugin-module"
15+
},
16+
"exports": {
17+
".": "./src/index.ts",
18+
"./alpha": "./src/alpha.ts",
19+
"./package.json": "./package.json"
20+
},
21+
"typesVersions": {
22+
"*": {
23+
"alpha": [
24+
"src/alpha.ts"
25+
],
26+
"package.json": [
27+
"package.json"
28+
]
29+
}
1530
},
1631
"scripts": {
1732
"start": "opener http://localhost:8080/admin/master/console/#/janus-realm && opener http://localhost:7007/catalog/entities && turbo run start:plugin start:keycloak",
@@ -23,10 +38,12 @@
2338
"test": "backstage-cli package test --passWithNoTests --coverage",
2439
"clean": "backstage-cli package clean",
2540
"prepack": "backstage-cli package prepack",
26-
"postpack": "backstage-cli package postpack"
41+
"postpack": "backstage-cli package postpack",
42+
"export-dynamic": "janus-cli package export-dynamic-plugin"
2743
},
2844
"dependencies": {
2945
"@backstage/backend-common": "^0.19.8",
46+
"@backstage/backend-plugin-api": "^0.6.6",
3047
"@backstage/backend-tasks": "^0.5.11",
3148
"@backstage/catalog-model": "^1.4.3",
3249
"@backstage/config": "^1.1.1",
@@ -38,22 +55,28 @@
3855
},
3956
"devDependencies": {
4057
"@backstage/backend-app-api": "0.5.6",
58+
"@backstage/backend-test-utils": "^0.2.7",
4159
"@backstage/cli": "0.23.0",
4260
"@backstage/plugin-auth-node": "0.4.0",
4361
"@backstage/plugin-catalog-backend": "1.14.0",
4462
"@backstage/plugin-permission-common": "0.7.9",
4563
"@backstage/plugin-permission-node": "0.7.17",
64+
"@janus-idp/cli": "1.1.0",
4665
"@types/lodash": "4.14.200",
4766
"@types/supertest": "2.0.14",
4867
"@types/uuid": "9.0.5",
4968
"deepmerge": "4.3.1",
5069
"express": "4.18.2",
70+
"luxon": "^3.4.3",
5171
"msw": "1.3.2",
5272
"opener": "1.5.2",
5373
"supertest": "6.3.3"
5474
},
5575
"files": [
5676
"dist",
77+
"dist-dynamic/*.*",
78+
"dist-dynamic/dist/**",
79+
"dist-dynamic/alpha/*",
5780
"config.d.ts"
5881
],
5982
"configSchema": "config.d.ts",

plugins/keycloak-backend/src/alpha.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2023 The Janus IDP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* The Keycloak backend plugin integrates Keycloak into Backstage
19+
*
20+
* @packageDocumentation
21+
*/
22+
23+
export * from './module';
24+
export { default } from './module';
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2023 The Janus IDP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { TaskScheduleDefinition } from '@backstage/backend-tasks';
18+
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
19+
import { EntityProvider } from '@backstage/plugin-catalog-node';
20+
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
21+
22+
import { Duration } from 'luxon';
23+
24+
import { catalogModuleKeycloakEntityProvider } from './catalogModuleKeycloakEntityProvider';
25+
26+
describe('catalogModuleKeycloakEntityProvider', () => {
27+
it('should register provider at the catalog extension point', async () => {
28+
let addedProviders: Array<EntityProvider> | undefined;
29+
let usedSchedule: TaskScheduleDefinition | undefined;
30+
31+
const extensionPoint = {
32+
addEntityProvider: (providers: any) => {
33+
addedProviders = providers;
34+
},
35+
};
36+
const runner = jest.fn();
37+
const scheduler = mockServices.scheduler.mock({
38+
createScheduledTaskRunner(schedule) {
39+
usedSchedule = schedule;
40+
return { run: runner };
41+
},
42+
});
43+
44+
const config = {
45+
catalog: {
46+
providers: {
47+
keycloakOrg: {
48+
default: {
49+
baseUrl: 'https://example.com/auth',
50+
schedule: {
51+
frequency: 'P1M',
52+
timeout: 'PT3M',
53+
},
54+
},
55+
},
56+
},
57+
},
58+
};
59+
60+
await startTestBackend({
61+
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
62+
features: [
63+
catalogModuleKeycloakEntityProvider(),
64+
mockServices.rootConfig.factory({ data: config }),
65+
scheduler.factory,
66+
],
67+
});
68+
69+
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
70+
expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
71+
expect(addedProviders?.length).toEqual(1);
72+
expect(addedProviders?.pop()?.getProviderName()).toEqual(
73+
'KeycloakOrgEntityProvider:default',
74+
);
75+
expect(runner).not.toHaveBeenCalled();
76+
});
77+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2023 The Janus IDP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { loggerToWinstonLogger } from '@backstage/backend-common';
18+
import {
19+
coreServices,
20+
createBackendModule,
21+
} from '@backstage/backend-plugin-api';
22+
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
23+
24+
import { KeycloakOrgEntityProvider } from '../providers';
25+
26+
/**
27+
* Registers the `KeycloakEntityProvider` with the catalog processing extension point.
28+
*
29+
* @alpha
30+
*/
31+
export const catalogModuleKeycloakEntityProvider = createBackendModule({
32+
pluginId: 'catalog',
33+
moduleId: 'keycloakEntityProvider',
34+
register(env) {
35+
env.registerInit({
36+
deps: {
37+
catalog: catalogProcessingExtensionPoint,
38+
config: coreServices.rootConfig,
39+
logger: coreServices.logger,
40+
scheduler: coreServices.scheduler,
41+
},
42+
async init({ catalog, config, logger, scheduler }) {
43+
catalog.addEntityProvider(
44+
KeycloakOrgEntityProvider.fromConfig(config, {
45+
id: 'development',
46+
logger: loggerToWinstonLogger(logger),
47+
scheduler,
48+
}),
49+
);
50+
},
51+
});
52+
},
53+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2023 The Janus IDP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
export { catalogModuleKeycloakEntityProvider as default } from './catalogModuleKeycloakEntityProvider';

0 commit comments

Comments
 (0)