feat(kubernetes): update k8s-backend plugin to use label selectors
update plugin to use label selectors when querying backend
This commit is contained in:
committed by
moustafab
parent
da2f4cd41a
commit
e2085293a6
@@ -57,7 +57,7 @@ describe('KubernetesClientProvider', () => {
|
||||
|
||||
clientMock.listServiceForAllNamespaces.mockRejectedValue(errorResponse);
|
||||
|
||||
const result = await sut.fetchObjectsByServiceId(
|
||||
const result = await sut.fetchObjectsForService(
|
||||
'some-service',
|
||||
{
|
||||
name: 'cluster1',
|
||||
@@ -120,7 +120,7 @@ describe('KubernetesClientProvider', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const result = await sut.fetchObjectsByServiceId(
|
||||
const result = await sut.fetchObjectsForService(
|
||||
'some-service',
|
||||
{
|
||||
name: 'cluster1',
|
||||
@@ -169,7 +169,7 @@ describe('KubernetesClientProvider', () => {
|
||||
});
|
||||
it('should throw error on unknown type', () => {
|
||||
expect(() =>
|
||||
sut.fetchObjectsByServiceId(
|
||||
sut.fetchObjectsForService(
|
||||
'some-service',
|
||||
{
|
||||
name: 'cluster1',
|
||||
|
||||
@@ -105,15 +105,19 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
fetchObjectsByServiceId(
|
||||
fetchObjectsForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
objectTypesToFetch: Set<KubernetesObjectTypes>,
|
||||
labelSelector: string,
|
||||
): Promise<FetchResponseWrapper> {
|
||||
const fetchResults = Array.from(objectTypesToFetch).map(type => {
|
||||
return this.fetchByObjectType(serviceId, clusterDetails, type).catch(
|
||||
captureKubernetesErrorsRethrowOthers,
|
||||
);
|
||||
return this.fetchByObjectType(
|
||||
serviceId,
|
||||
clusterDetails,
|
||||
type,
|
||||
labelSelector,
|
||||
).catch(captureKubernetesErrorsRethrowOthers);
|
||||
});
|
||||
|
||||
return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);
|
||||
@@ -124,42 +128,53 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher {
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
type: KubernetesObjectTypes,
|
||||
labelSelector: string,
|
||||
): Promise<FetchResponse> {
|
||||
switch (type) {
|
||||
case 'pods':
|
||||
return this.fetchPodsByServiceId(serviceId, clusterDetails).then(r => ({
|
||||
return this.fetchPodsForService(
|
||||
serviceId,
|
||||
clusterDetails,
|
||||
labelSelector,
|
||||
).then(r => ({
|
||||
type: type,
|
||||
resources: r,
|
||||
}));
|
||||
case 'configmaps':
|
||||
return this.fetchConfigMapsByServiceId(
|
||||
return this.fetchConfigMapsForService(
|
||||
serviceId,
|
||||
clusterDetails,
|
||||
labelSelector,
|
||||
).then(r => ({ type: type, resources: r }));
|
||||
case 'deployments':
|
||||
return this.fetchDeploymentsByServiceId(
|
||||
return this.fetchDeploymentsForService(
|
||||
serviceId,
|
||||
clusterDetails,
|
||||
labelSelector,
|
||||
).then(r => ({ type: type, resources: r }));
|
||||
case 'replicasets':
|
||||
return this.fetchReplicaSetsByServiceId(
|
||||
return this.fetchReplicaSetsForService(
|
||||
serviceId,
|
||||
clusterDetails,
|
||||
labelSelector,
|
||||
).then(r => ({ type: type, resources: r }));
|
||||
case 'services':
|
||||
return this.fetchServicesByServiceId(
|
||||
return this.fetchServicesForService(
|
||||
serviceId,
|
||||
clusterDetails,
|
||||
labelSelector,
|
||||
).then(r => ({ type: type, resources: r }));
|
||||
case 'horizontalpodautoscalers':
|
||||
return this.fetchHorizontalPodAutoscalersByServiceId(
|
||||
return this.fetchHorizontalPodAutoscalersForService(
|
||||
serviceId,
|
||||
clusterDetails,
|
||||
labelSelector,
|
||||
).then(r => ({ type: type, resources: r }));
|
||||
case 'ingresses':
|
||||
return this.fetchIngressesByServiceId(
|
||||
return this.fetchIngressesForService(
|
||||
serviceId,
|
||||
clusterDetails,
|
||||
labelSelector,
|
||||
).then(r => ({ type: type, resources: r }));
|
||||
default:
|
||||
// unrecognised type
|
||||
@@ -192,79 +207,60 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher {
|
||||
});
|
||||
}
|
||||
|
||||
private fetchServicesByServiceId(
|
||||
private fetchServicesForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
labelSelector: string,
|
||||
): Promise<Array<V1Service>> {
|
||||
return this.singleClusterFetch<V1Service>(clusterDetails, ({ core }) =>
|
||||
core.listServiceForAllNamespaces(
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
`backstage.io/kubernetes-id=${serviceId}`,
|
||||
),
|
||||
core.listServiceForAllNamespaces(false, '', '', labelSelector),
|
||||
);
|
||||
}
|
||||
|
||||
private fetchPodsByServiceId(
|
||||
private fetchPodsForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
labelSelector: string,
|
||||
): Promise<Array<V1Pod>> {
|
||||
return this.singleClusterFetch<V1Pod>(clusterDetails, ({ core }) =>
|
||||
core.listPodForAllNamespaces(
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
`backstage.io/kubernetes-id=${serviceId}`,
|
||||
),
|
||||
core.listPodForAllNamespaces(false, '', '', labelSelector),
|
||||
);
|
||||
}
|
||||
|
||||
private fetchConfigMapsByServiceId(
|
||||
private fetchConfigMapsForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
labelSelector: string,
|
||||
): Promise<Array<V1ConfigMap>> {
|
||||
return this.singleClusterFetch<V1Pod>(clusterDetails, ({ core }) =>
|
||||
core.listConfigMapForAllNamespaces(
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
`backstage.io/kubernetes-id=${serviceId}`,
|
||||
),
|
||||
core.listConfigMapForAllNamespaces(false, '', '', labelSelector),
|
||||
);
|
||||
}
|
||||
|
||||
private fetchDeploymentsByServiceId(
|
||||
private fetchDeploymentsForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
labelSelector: string,
|
||||
): Promise<Array<V1Deployment>> {
|
||||
return this.singleClusterFetch<V1Deployment>(clusterDetails, ({ apps }) =>
|
||||
apps.listDeploymentForAllNamespaces(
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
`backstage.io/kubernetes-id=${serviceId}`,
|
||||
),
|
||||
apps.listDeploymentForAllNamespaces(false, '', '', labelSelector),
|
||||
);
|
||||
}
|
||||
|
||||
private fetchReplicaSetsByServiceId(
|
||||
private fetchReplicaSetsForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
labelSelector: string,
|
||||
): Promise<Array<V1ReplicaSet>> {
|
||||
return this.singleClusterFetch<V1ReplicaSet>(clusterDetails, ({ apps }) =>
|
||||
apps.listReplicaSetForAllNamespaces(
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
`backstage.io/kubernetes-id=${serviceId}`,
|
||||
),
|
||||
apps.listReplicaSetForAllNamespaces(false, '', '', labelSelector),
|
||||
);
|
||||
}
|
||||
|
||||
private fetchHorizontalPodAutoscalersByServiceId(
|
||||
private fetchHorizontalPodAutoscalersForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
labelSelector: string,
|
||||
): Promise<Array<V1HorizontalPodAutoscaler>> {
|
||||
return this.singleClusterFetch<V1HorizontalPodAutoscaler>(
|
||||
clusterDetails,
|
||||
@@ -273,14 +269,15 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher {
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
`backstage.io/kubernetes-id=${serviceId}`,
|
||||
labelSelector,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private fetchIngressesByServiceId(
|
||||
private fetchIngressesForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
labelSelector: string,
|
||||
): Promise<Array<ExtensionsV1beta1Ingress>> {
|
||||
return this.singleClusterFetch<ExtensionsV1beta1Ingress>(
|
||||
clusterDetails,
|
||||
@@ -289,7 +286,7 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher {
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
`backstage.io/kubernetes-id=${serviceId}`,
|
||||
labelSelector,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
+5
-5
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { handleGetKubernetesObjectsByServiceId } from './getKubernetesObjectsByServiceIdHandler';
|
||||
import { handleGetKubernetesObjectsForService } from './getKubernetesObjectsForServiceHandler';
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { ClusterDetails } from '..';
|
||||
|
||||
@@ -81,10 +81,10 @@ describe('handleGetKubernetesObjectsByServiceId', () => {
|
||||
|
||||
mockFetch(fetchObjectsByServiceId);
|
||||
|
||||
const result = await handleGetKubernetesObjectsByServiceId(
|
||||
const result = await handleGetKubernetesObjectsForService(
|
||||
TEST_SERVICE_ID,
|
||||
{
|
||||
fetchObjectsByServiceId,
|
||||
fetchObjectsForService: fetchObjectsByServiceId,
|
||||
},
|
||||
{
|
||||
getClustersByServiceId,
|
||||
@@ -155,10 +155,10 @@ describe('handleGetKubernetesObjectsByServiceId', () => {
|
||||
|
||||
mockFetch(fetchObjectsByServiceId);
|
||||
|
||||
const result = await handleGetKubernetesObjectsByServiceId(
|
||||
const result = await handleGetKubernetesObjectsForService(
|
||||
TEST_SERVICE_ID,
|
||||
{
|
||||
fetchObjectsByServiceId,
|
||||
fetchObjectsForService: fetchObjectsByServiceId,
|
||||
},
|
||||
{
|
||||
getClustersByServiceId,
|
||||
|
||||
+5
-3
@@ -26,12 +26,13 @@ import {
|
||||
import { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';
|
||||
import { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';
|
||||
|
||||
export type GetKubernetesObjectsByServiceIdHandler = (
|
||||
export type GetKubernetesObjectsForServiceHandler = (
|
||||
serviceId: string,
|
||||
fetcher: KubernetesFetcher,
|
||||
serviceLocator: KubernetesServiceLocator,
|
||||
logger: Logger,
|
||||
requestBody: AuthRequestBody,
|
||||
labelSelector: string,
|
||||
objectsToFetch?: Set<KubernetesObjectTypes>,
|
||||
) => Promise<ObjectsByServiceIdResponse>;
|
||||
|
||||
@@ -46,12 +47,13 @@ const DEFAULT_OBJECTS = new Set<KubernetesObjectTypes>([
|
||||
]);
|
||||
|
||||
// Fans out the request to all clusters that the service lives in, aggregates their responses together
|
||||
export const handleGetKubernetesObjectsByServiceId: GetKubernetesObjectsByServiceIdHandler = async (
|
||||
export const handleGetKubernetesObjectsForService: GetKubernetesObjectsForServiceHandler = async (
|
||||
serviceId,
|
||||
fetcher,
|
||||
serviceLocator,
|
||||
logger,
|
||||
requestBody,
|
||||
labelSelector: string,
|
||||
objectsToFetch = DEFAULT_OBJECTS,
|
||||
) => {
|
||||
const clusterDetails: ClusterDetails[] = await serviceLocator.getClustersByServiceId(
|
||||
@@ -81,7 +83,7 @@ export const handleGetKubernetesObjectsByServiceId: GetKubernetesObjectsByServic
|
||||
return Promise.all(
|
||||
clusterDetailsDecoratedForAuth.map(cd => {
|
||||
return fetcher
|
||||
.fetchObjectsByServiceId(serviceId, cd, objectsToFetch)
|
||||
.fetchObjectsForService(serviceId, cd, objectsToFetch, labelSelector)
|
||||
.then(result => {
|
||||
return {
|
||||
cluster: {
|
||||
@@ -32,7 +32,7 @@ describe('router', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
kubernetesFetcher = {
|
||||
fetchObjectsByServiceId: jest.fn(),
|
||||
fetchObjectsForService: jest.fn(),
|
||||
};
|
||||
|
||||
kubernetesServiceLocator = {
|
||||
|
||||
@@ -22,9 +22,9 @@ import { MultiTenantServiceLocator } from '../service-locator/MultiTenantService
|
||||
import { KubernetesClientBasedFetcher } from './KubernetesFetcher';
|
||||
import { KubernetesClientProvider } from './KubernetesClientProvider';
|
||||
import {
|
||||
GetKubernetesObjectsByServiceIdHandler,
|
||||
handleGetKubernetesObjectsByServiceId,
|
||||
} from './getKubernetesObjectsByServiceIdHandler';
|
||||
GetKubernetesObjectsForServiceHandler,
|
||||
handleGetKubernetesObjectsForService,
|
||||
} from './getKubernetesObjectsForServiceHandler';
|
||||
import {
|
||||
AuthRequestBody,
|
||||
KubernetesServiceLocator,
|
||||
@@ -64,13 +64,14 @@ export const makeRouter = (
|
||||
logger: Logger,
|
||||
fetcher: KubernetesFetcher,
|
||||
serviceLocator: KubernetesServiceLocator,
|
||||
handleGetByServiceId: GetKubernetesObjectsByServiceIdHandler,
|
||||
handleGetByServiceId: GetKubernetesObjectsForServiceHandler,
|
||||
): express.Router => {
|
||||
const router = Router();
|
||||
router.use(express.json());
|
||||
|
||||
router.post('/services/:serviceId', async (req, res) => {
|
||||
const serviceId = req.params.serviceId;
|
||||
const labelSelector = req.query.labelSelector;
|
||||
const requestBody: AuthRequestBody = req.body;
|
||||
try {
|
||||
const response = await handleGetByServiceId(
|
||||
@@ -79,6 +80,7 @@ export const makeRouter = (
|
||||
serviceLocator,
|
||||
logger,
|
||||
requestBody,
|
||||
labelSelector,
|
||||
);
|
||||
res.send(response);
|
||||
} catch (e) {
|
||||
@@ -119,6 +121,6 @@ export async function createRouter(
|
||||
logger,
|
||||
fetcher,
|
||||
serviceLocator,
|
||||
handleGetKubernetesObjectsByServiceId,
|
||||
handleGetKubernetesObjectsForService,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,10 +110,11 @@ export interface IngressesFetchResponse {
|
||||
// Fetches information from a kubernetes cluster using the cluster details object
|
||||
// to target a specific cluster
|
||||
export interface KubernetesFetcher {
|
||||
fetchObjectsByServiceId(
|
||||
fetchObjectsForService(
|
||||
serviceId: string,
|
||||
clusterDetails: ClusterDetails,
|
||||
objectTypesToFetch: Set<KubernetesObjectTypes>,
|
||||
labelSelector: string,
|
||||
): Promise<FetchResponseWrapper>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user