Skip to content

Commit d33cc4a

Browse files
authored
copy modelcatalog.api.annotations to component annotations (#1486)
1 parent 02164f8 commit d33cc4a

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/ModelCatalogGenerator.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,4 +432,88 @@ describe('Model Catalog Generator', () => {
432432
expectedEntities.push(expectedModelServerAPIEntity);
433433
expect(modelCatalogEntities).toEqual(expectedModelEntities);
434434
});
435+
436+
it('should copy API annotations to model server component metadata when present', () => {
437+
const modelCatalog: ModelCatalog = {
438+
modelServer: {
439+
name: 'annotated-model-service',
440+
owner: 'example-user',
441+
description: 'Model service with API annotations',
442+
API: {
443+
url: 'https://api.example.com',
444+
type: Type.Openapi,
445+
spec: 'https://example.com/openapi.json',
446+
annotations: {
447+
'custom.io/annotation1': 'value1',
448+
'custom.io/annotation2': 'value2',
449+
'backstage.io/custom-tag': 'custom-value',
450+
},
451+
},
452+
lifecycle: 'production',
453+
},
454+
models: [
455+
{
456+
name: 'test-model',
457+
description: 'Test model',
458+
lifecycle: 'production',
459+
owner: 'example-user',
460+
},
461+
],
462+
};
463+
464+
const modelCatalogEntities = GenerateCatalogEntities(modelCatalog);
465+
466+
// Find the model server component entity
467+
const modelServerComponent = modelCatalogEntities.find(
468+
entity =>
469+
entity.kind === 'Component' &&
470+
entity.metadata.name === 'annotated-model-service',
471+
) as ComponentEntity;
472+
473+
expect(modelServerComponent).toBeDefined();
474+
expect(modelServerComponent.metadata.annotations).toBeDefined();
475+
expect(modelServerComponent.metadata.annotations).toEqual({
476+
'custom.io/annotation1': 'value1',
477+
'custom.io/annotation2': 'value2',
478+
'backstage.io/custom-tag': 'custom-value',
479+
});
480+
});
481+
482+
it('should handle model server with API but no annotations gracefully', () => {
483+
const modelCatalog: ModelCatalog = {
484+
modelServer: {
485+
name: 'no-annotations-service',
486+
owner: 'example-user',
487+
description: 'Model service without API annotations',
488+
API: {
489+
url: 'https://api.example.com',
490+
type: Type.Openapi,
491+
spec: 'https://example.com/openapi.json',
492+
// No annotations property
493+
},
494+
lifecycle: 'production',
495+
},
496+
models: [
497+
{
498+
name: 'test-model',
499+
description: 'Test model',
500+
lifecycle: 'production',
501+
owner: 'example-user',
502+
},
503+
],
504+
};
505+
506+
const modelCatalogEntities = GenerateCatalogEntities(modelCatalog);
507+
508+
// Find the model server component entity
509+
const modelServerComponent = modelCatalogEntities.find(
510+
entity =>
511+
entity.kind === 'Component' &&
512+
entity.metadata.name === 'no-annotations-service',
513+
) as ComponentEntity;
514+
515+
expect(modelServerComponent).toBeDefined();
516+
// Should not have annotations if none were provided in API
517+
expect(modelServerComponent.metadata.annotations).toBeUndefined();
518+
});
435519
});

workspaces/ai-integrations/plugins/catalog-backend-module-model-catalog/src/clients/ModelCatalogGenerator.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,18 @@ export function GenerateModelServerComponentEntity(
194194
url: `${modelServer.API.url}`,
195195
});
196196
modelServerComponent.spec.providesApis = [modelServer.name];
197+
198+
// Copy annotations from API to component metadata if they exist
199+
if (modelServer.API.annotations !== undefined) {
200+
if (modelServerComponent.metadata.annotations === undefined) {
201+
modelServerComponent.metadata.annotations = {};
202+
}
203+
// Copy all key-value pairs from API annotations to component annotations
204+
Object.keys(modelServer.API.annotations).forEach(key => {
205+
modelServerComponent.metadata.annotations![key] =
206+
modelServer.API!.annotations![key];
207+
});
208+
}
197209
}
198210
if (modelServer.homepageURL !== undefined) {
199211
modelServerComponent.metadata.links.push({

0 commit comments

Comments
 (0)