feat: add an instance metadata experimental service

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
This commit is contained in:
aramissennyeydd
2024-11-28 16:59:40 -05:00
parent 82aa728618
commit 660915e983
5 changed files with 177 additions and 0 deletions
@@ -724,4 +724,59 @@ describe('BackendInitializer', () => {
await init.start();
});
it('should properly add plugins + modules to the instance metadata service', async () => {
expect.assertions(1);
const backend = new BackendInitializer(baseFactories);
const plugin = createBackendPlugin({
pluginId: 'test',
register(reg) {
reg.registerInit({
deps: {},
async init() {},
});
},
});
const instanceMetadataPlugin = createBackendPlugin({
pluginId: 'instance-metadata',
register(reg) {
reg.registerInit({
deps: {
instanceMetadata: coreServices.EXPERIMENTAL_instanceMetadata,
},
async init({ instanceMetadata }) {
expect(instanceMetadata.getInstalledFeatures()).toEqual([
{
pluginId: 'test',
type: 'plugin',
},
{
pluginId: 'test',
moduleId: 'test',
type: 'module',
},
{
pluginId: 'instance-metadata',
type: 'plugin',
},
]);
},
});
},
});
const module = createBackendModule({
pluginId: 'test',
moduleId: 'test',
register(reg) {
reg.registerInit({
deps: {},
async init() {},
});
},
});
backend.add(plugin);
backend.add(module);
backend.add(instanceMetadataPlugin);
await backend.start();
});
});
@@ -22,6 +22,7 @@ import {
ServiceFactory,
LifecycleService,
RootLifecycleService,
createServiceFactory,
} from '@backstage/backend-plugin-api';
import { ServiceOrExtensionPoint } from './types';
// Direct internal import to avoid duplication
@@ -96,6 +97,49 @@ const instanceRegistry = new (class InstanceRegistry {
};
})();
type BackendFeatureMeta =
| {
type: 'plugin';
pluginId: string;
}
| {
type: 'module';
pluginId: string;
moduleId: string;
};
function createInstanceMetadataServiceFactory(
registrations: InternalBackendRegistrations[],
) {
const installedFeatures = registrations
.map(registration => {
if (registration.featureType === 'registrations') {
return registration
.getRegistrations()
.map(feature => {
if (feature.type === 'plugin') {
return { type: 'plugin', pluginId: feature.pluginId };
} else if (feature.type === 'module') {
return {
type: 'module',
pluginId: feature.pluginId,
moduleId: feature.moduleId,
};
}
return undefined;
})
.filter(Boolean) as BackendFeatureMeta[];
}
return [];
})
.flat();
return createServiceFactory({
service: coreServices.EXPERIMENTAL_instanceMetadata,
deps: {},
factory: async () => ({ getInstalledFeatures: () => installedFeatures }),
});
}
export class BackendInitializer {
#startPromise?: Promise<void>;
#stopPromise?: Promise<void>;
@@ -210,6 +254,10 @@ export class BackendInitializer {
await this.#applyBackendFeatureLoaders(this.#registeredFeatureLoaders);
this.#serviceRegistry.add(
createInstanceMetadataServiceFactory(this.#registrations),
);
// Initialize all root scoped services
await this.#serviceRegistry.initializeEagerServicesWithScope('root');
@@ -0,0 +1,30 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type BackendFeatureMeta =
| {
type: 'plugin';
pluginId: string;
}
| {
type: 'module';
pluginId: string;
moduleId: string;
};
export interface InstanceMetadataService {
getInstalledFeatures: () => BackendFeatureMeta[];
}
@@ -251,4 +251,15 @@ export namespace coreServices {
export const urlReader = createServiceRef<
import('./UrlReaderService').UrlReaderService
>({ id: 'core.urlReader' });
/**
* EXPERIMENTAL: Instance metadata service.
*
* @public
*/
export const EXPERIMENTAL_instanceMetadata = createServiceRef<
import('./InstanceMetadataService').InstanceMetadataService
>({
id: 'core.instanceMetadata',
});
}
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
coreServices,
createBackendPlugin,
} from '@backstage/backend-plugin-api';
export default createBackendPlugin({
pluginId: 'instance-metadata-logging',
register(env) {
env.registerInit({
deps: {
instanceMetadata: coreServices.EXPERIMENTAL_instanceMetadata,
},
async init({ instanceMetadata }) {
console.log('metadata', instanceMetadata.getInstalledFeatures());
},
});
},
});