add kubernetes namespace annotation

Signed-off-by: Matthew Clarke <mclarke@spotify.com>
This commit is contained in:
Matthew Clarke
2022-04-11 21:55:40 -04:00
parent 1f873a0908
commit 17a86fb29f
4 changed files with 92 additions and 14 deletions
@@ -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(
@@ -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");
});
});
@@ -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<FetchResponse> {
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,
};
});
}
}
}
@@ -34,6 +34,7 @@ export interface ObjectFetchParams {
objectTypesToFetch: Set<ObjectToFetch>;
labelSelector: string;
customResources: CustomResource[];
namespace?: string;
}
// Fetches information from a kubernetes cluster using the cluster details object