diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index 0db65d87d7..e35230f34f 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -207,6 +207,11 @@ export class KubernetesFanOutHandler { 'backstage.io/kubernetes-label-selector' ] || `backstage.io/kubernetes-id=${entityName}`; + const namespace = + requestBody.entity?.metadata?.annotations?.[ + 'backstage.io/kubernetes-namespace' + ]; + return Promise.all( clusterDetailsDecoratedForAuth.map(clusterDetailsItem => { return this.fetcher @@ -216,19 +221,24 @@ export class KubernetesFanOutHandler { objectTypesToFetch: this.objectTypesToFetch, labelSelector, customResources: this.customResources, + namespace }) .then(result => this.getMetricsForPods(clusterDetailsItem, result)) .then(r => this.toClusterObjects(clusterDetailsItem, r)); }), - ).then(r => ({ - items: r.filter( - item => - (item.errors !== undefined && item.errors.length >= 1) || - (item.resources !== undefined && - item.resources.length >= 1 && - item.resources.some(fr => fr.resources.length >= 1)), - ), - })); + ).then(this.toObjectsByEntityResponse); + } + + toObjectsByEntityResponse(clusterObjects: ClusterObjects[]):ObjectsByEntityResponse { +return { + items: clusterObjects.filter( + item => + (item.errors !== undefined && item.errors.length >= 1) || + (item.resources !== undefined && + item.resources.length >= 1 && + item.resources.some(fr => fr.resources.length >= 1)), + ), +} } toClusterObjects( diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts index e1f701b75c..5ba64dd53a 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts @@ -42,6 +42,7 @@ describe('KubernetesFetcher', () => { jest.resetAllMocks(); clientMock = { listClusterCustomObject: jest.fn(), + listNamespacedCustomObject: jest.fn(), addInterceptor: jest.fn(), }; @@ -479,4 +480,47 @@ describe('KubernetesFetcher', () => { const expectedSelector = 'backstage.io/kubernetes-id=some-service'; expect(actualSelector).toBe(expectedSelector); }); + it('should use namespace if provided', async () => { + clientMock.listNamespacedCustomObject.mockResolvedValueOnce({ + body: { + items: [ + { + metadata: { + name: 'pod-name', + }, + }, + ], + }, + }); + + clientMock.listNamespacedCustomObject.mockResolvedValueOnce({ + body: { + items: [ + { + metadata: { + name: 'service-name', + }, + }, + ], + }, + }); + + await sut.fetchObjectsForService({ + serviceId: 'some-service', + clusterDetails: { + name: 'cluster1', + url: 'http://localhost:9999', + serviceAccountToken: 'token', + authProvider: 'serviceAccount', + }, + objectTypesToFetch: OBJECTS_TO_FETCH, + labelSelector: '', + namespace: "some-namespace", + customResources: [], + }); + + const mockCall = clientMock.listNamespacedCustomObject.mock.calls[0]; + const namespace = mockCall[2] + expect(namespace).toBe("some-namespace"); + }); }); diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts index a2c3b9a6a8..0e4f32b0c3 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts @@ -97,6 +97,7 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { params.labelSelector || `backstage.io/kubernetes-id=${params.serviceId}`, toFetch.objectType, + params.namespace ).catch(this.captureKubernetesErrorsRethrowOthers.bind(this)); }); @@ -138,18 +139,21 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { resource: ObjectToFetch, labelSelector: string, objectType: KubernetesObjectTypes, + namespace?: string ): Promise { const customObjects = this.kubernetesClientProvider.getCustomObjectsClient(clusterDetails); - customObjects.addInterceptor((requestOptions: any) => { - requestOptions.uri = requestOptions.uri.replace('/apis//v1/', '/api/v1/'); - }); + customObjects.addInterceptor((requestOptions: any) => { + requestOptions.uri = requestOptions.uri.replace('/apis//v1/', '/api/v1/'); + }); - return customObjects - .listClusterCustomObject( + if(namespace){ + return customObjects + .listNamespacedCustomObject( resource.group, resource.apiVersion, + namespace, resource.plural, '', false, @@ -163,5 +167,24 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { resources: (r.body as any).items, }; }); + } else { + return customObjects + .listClusterCustomObject( + resource.group, + resource.apiVersion, + resource.plural, + '', + false, + '', + '', + labelSelector, + ) + .then(r => { + return { + type: objectType, + resources: (r.body as any).items, + }; + }); + } } } diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 2d7e2d3da7..12c4d2fb48 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -34,6 +34,7 @@ export interface ObjectFetchParams { objectTypesToFetch: Set; labelSelector: string; customResources: CustomResource[]; + namespace?: string; } // Fetches information from a kubernetes cluster using the cluster details object