convert fetchObjectsForService mocks to msw
this will allow some dramatic refactoring Signed-off-by: Jamie Klassen <jklassen@vmware.com>
This commit is contained in:
@@ -16,8 +16,12 @@
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { KubernetesClientBasedFetcher } from './KubernetesFetcher';
|
||||
import { KubernetesClientProvider } from './KubernetesClientProvider';
|
||||
import { ObjectToFetch } from '../types/types';
|
||||
import { topPods } from '@kubernetes/client-node';
|
||||
import { MockedRequest, rest } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { setupRequestMockHandlers } from '@backstage/backend-test-utils';
|
||||
|
||||
jest.mock('@kubernetes/client-node', () => ({
|
||||
...jest.requireActual('@kubernetes/client-node'),
|
||||
@@ -56,45 +60,43 @@ const POD_METRICS_FIXTURE = {
|
||||
|
||||
describe('KubernetesFetcher', () => {
|
||||
describe('fetchObjectsForService', () => {
|
||||
let clientMock: any;
|
||||
let kubernetesClientProvider: any;
|
||||
let sut: KubernetesClientBasedFetcher;
|
||||
const worker = setupServer();
|
||||
setupRequestMockHandlers(worker);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
clientMock = {
|
||||
listClusterCustomObject: jest.fn(),
|
||||
listNamespacedCustomObject: jest.fn(),
|
||||
addInterceptor: jest.fn(),
|
||||
};
|
||||
|
||||
kubernetesClientProvider = {
|
||||
getCustomObjectsClient: jest.fn(() => clientMock),
|
||||
};
|
||||
|
||||
sut = new KubernetesClientBasedFetcher({
|
||||
kubernetesClientProvider,
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
});
|
||||
const labels = (req: MockedRequest): object => {
|
||||
const selectorParam = req.url.searchParams.get('labelSelector');
|
||||
if (selectorParam) {
|
||||
const [key, value] = selectorParam.split('=');
|
||||
return { [key]: value };
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
const testErrorResponse = async (
|
||||
errorResponse: any,
|
||||
expectedResult: any,
|
||||
) => {
|
||||
clientMock.listClusterCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
clientMock.listClusterCustomObject.mockRejectedValue(errorResponse);
|
||||
worker.use(
|
||||
rest.get('http://localhost:9999/api/v1/pods', (req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [{ metadata: { name: 'pod-name', labels: labels(req) } }],
|
||||
}),
|
||||
),
|
||||
),
|
||||
rest.get('http://localhost:9999/api/v1/services', (_, res, ctx) => {
|
||||
return res(
|
||||
ctx.status(errorResponse.response.statusCode),
|
||||
ctx.json({
|
||||
kind: 'Status',
|
||||
apiVersion: 'v1',
|
||||
status: 'Failure',
|
||||
code: errorResponse.response.statusCode,
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await sut.fetchObjectsForService({
|
||||
serviceId: 'some-service',
|
||||
@@ -118,66 +120,41 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
labels: { 'backstage.io/kubernetes-id': 'some-service' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls.length).toBe(2);
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls[0]).toEqual([
|
||||
'',
|
||||
'v1',
|
||||
'pods',
|
||||
'',
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
'backstage.io/kubernetes-id=some-service',
|
||||
]);
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls[1]).toEqual([
|
||||
'',
|
||||
'v1',
|
||||
'services',
|
||||
'',
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
'backstage.io/kubernetes-id=some-service',
|
||||
]);
|
||||
|
||||
expect(
|
||||
kubernetesClientProvider.getCustomObjectsClient.mock.calls.length,
|
||||
).toBe(2);
|
||||
};
|
||||
|
||||
it('should return pods, services', async () => {
|
||||
clientMock.listClusterCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
beforeEach(() => {
|
||||
sut = new KubernetesClientBasedFetcher({
|
||||
kubernetesClientProvider: new KubernetesClientProvider(),
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
});
|
||||
|
||||
clientMock.listClusterCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'service-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
it('should return pods, services', async () => {
|
||||
worker.use(
|
||||
rest.get('http://localhost:9999/api/v1/pods', (req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [{ metadata: { name: 'pod-name', labels: labels(req) } }],
|
||||
}),
|
||||
),
|
||||
),
|
||||
rest.get('http://localhost:9999/api/v1/services', (req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{ metadata: { name: 'service-name', labels: labels(req) } },
|
||||
],
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
const result = await sut.fetchObjectsForService({
|
||||
serviceId: 'some-service',
|
||||
@@ -201,6 +178,7 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
labels: { 'backstage.io/kubernetes-id': 'some-service' },
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -211,77 +189,44 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
metadata: {
|
||||
name: 'service-name',
|
||||
labels: { 'backstage.io/kubernetes-id': 'some-service' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls.length).toBe(2);
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls[0]).toEqual([
|
||||
'',
|
||||
'v1',
|
||||
'pods',
|
||||
'',
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
'backstage.io/kubernetes-id=some-service',
|
||||
]);
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls[1]).toEqual([
|
||||
'',
|
||||
'v1',
|
||||
'services',
|
||||
'',
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
'backstage.io/kubernetes-id=some-service',
|
||||
]);
|
||||
|
||||
expect(
|
||||
kubernetesClientProvider.getCustomObjectsClient.mock.calls.length,
|
||||
).toBe(2);
|
||||
});
|
||||
it('should return pods, services and customobjects', async () => {
|
||||
clientMock.listClusterCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
clientMock.listClusterCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'service-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
clientMock.listClusterCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'something-else',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
worker.use(
|
||||
rest.get('http://localhost:9999/api/v1/pods', (req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [{ metadata: { name: 'pod-name', labels: labels(req) } }],
|
||||
}),
|
||||
),
|
||||
),
|
||||
rest.get('http://localhost:9999/api/v1/services', (req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{ metadata: { name: 'service-name', labels: labels(req) } },
|
||||
],
|
||||
}),
|
||||
),
|
||||
),
|
||||
rest.get(
|
||||
'http://localhost:9999/apis/some-group/v2/things',
|
||||
(req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{ metadata: { name: 'something-else', labels: labels(req) } },
|
||||
],
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
const result = await sut.fetchObjectsForService({
|
||||
serviceId: 'some-service',
|
||||
@@ -312,6 +257,7 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
labels: { 'backstage.io/kubernetes-id': 'some-service' },
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -322,6 +268,7 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
metadata: {
|
||||
name: 'service-name',
|
||||
labels: { 'backstage.io/kubernetes-id': 'some-service' },
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -332,51 +279,13 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
metadata: {
|
||||
name: 'something-else',
|
||||
labels: { 'backstage.io/kubernetes-id': 'some-service' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls.length).toBe(3);
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls[0]).toEqual([
|
||||
'',
|
||||
'v1',
|
||||
'pods',
|
||||
'',
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
'backstage.io/kubernetes-id=some-service',
|
||||
]);
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls[1]).toEqual([
|
||||
'',
|
||||
'v1',
|
||||
'services',
|
||||
'',
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
'backstage.io/kubernetes-id=some-service',
|
||||
]);
|
||||
|
||||
expect(clientMock.listClusterCustomObject.mock.calls[2]).toEqual([
|
||||
'some-group',
|
||||
'v2',
|
||||
'things',
|
||||
'',
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
'backstage.io/kubernetes-id=some-service',
|
||||
]);
|
||||
|
||||
expect(
|
||||
kubernetesClientProvider.getCustomObjectsClient.mock.calls.length,
|
||||
).toBe(3);
|
||||
});
|
||||
// they're in testErrorResponse
|
||||
// eslint-disable-next-line jest/expect-expect
|
||||
@@ -385,16 +294,11 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
response: {
|
||||
statusCode: 400,
|
||||
request: {
|
||||
uri: {
|
||||
pathname: '/some/path',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
errorType: 'BAD_REQUEST',
|
||||
resourcePath: '/some/path',
|
||||
resourcePath: '/api/v1/services',
|
||||
statusCode: 400,
|
||||
},
|
||||
);
|
||||
@@ -406,16 +310,11 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
response: {
|
||||
statusCode: 401,
|
||||
request: {
|
||||
uri: {
|
||||
pathname: '/some/path',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
errorType: 'UNAUTHORIZED_ERROR',
|
||||
resourcePath: '/some/path',
|
||||
resourcePath: '/api/v1/services',
|
||||
statusCode: 401,
|
||||
},
|
||||
);
|
||||
@@ -427,16 +326,11 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
response: {
|
||||
statusCode: 500,
|
||||
request: {
|
||||
uri: {
|
||||
pathname: '/some/path',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
errorType: 'SYSTEM_ERROR',
|
||||
resourcePath: '/some/path',
|
||||
resourcePath: '/api/v1/services',
|
||||
statusCode: 500,
|
||||
},
|
||||
);
|
||||
@@ -448,46 +342,36 @@ describe('KubernetesFetcher', () => {
|
||||
{
|
||||
response: {
|
||||
statusCode: 900,
|
||||
request: {
|
||||
uri: {
|
||||
pathname: '/some/path',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
errorType: 'UNKNOWN_ERROR',
|
||||
resourcePath: '/some/path',
|
||||
resourcePath: '/api/v1/services',
|
||||
statusCode: 900,
|
||||
},
|
||||
);
|
||||
});
|
||||
it('should always add a labelSelector query', async () => {
|
||||
clientMock.listClusterCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
it('should respect labelSelector', async () => {
|
||||
worker.use(
|
||||
rest.get('http://localhost:9999/api/v1/pods', (req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [{ metadata: { name: 'pod-name', labels: labels(req) } }],
|
||||
}),
|
||||
),
|
||||
),
|
||||
rest.get('http://localhost:9999/api/v1/services', (req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{ metadata: { name: 'service-name', labels: labels(req) } },
|
||||
],
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
clientMock.listClusterCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'service-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await sut.fetchObjectsForService({
|
||||
const result = await sut.fetchObjectsForService({
|
||||
serviceId: 'some-service',
|
||||
clusterDetails: {
|
||||
name: 'cluster1',
|
||||
@@ -496,41 +380,65 @@ describe('KubernetesFetcher', () => {
|
||||
authProvider: 'serviceAccount',
|
||||
},
|
||||
objectTypesToFetch: OBJECTS_TO_FETCH,
|
||||
labelSelector: '',
|
||||
labelSelector: 'service-label=value',
|
||||
customResources: [],
|
||||
});
|
||||
|
||||
const mockCall = clientMock.listClusterCustomObject.mock.calls[0];
|
||||
const actualSelector = mockCall[mockCall.length - 1];
|
||||
const expectedSelector = 'backstage.io/kubernetes-id=some-service';
|
||||
expect(actualSelector).toBe(expectedSelector);
|
||||
expect(result).toStrictEqual({
|
||||
errors: [],
|
||||
responses: [
|
||||
{
|
||||
type: 'pods',
|
||||
resources: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
labels: { 'service-label': 'value' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'services',
|
||||
resources: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'service-name',
|
||||
labels: { 'service-label': 'value' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
it('should use namespace if provided', async () => {
|
||||
clientMock.listNamespacedCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://localhost:9999/api/v1/namespaces/some-namespace/pods',
|
||||
(req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{ metadata: { name: 'pod-name', labels: labels(req) } },
|
||||
],
|
||||
}),
|
||||
),
|
||||
),
|
||||
rest.get(
|
||||
'http://localhost:9999/api/v1/namespaces/some-namespace/services',
|
||||
(req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
items: [
|
||||
{ metadata: { name: 'service-name', labels: labels(req) } },
|
||||
],
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
clientMock.listNamespacedCustomObject.mockResolvedValueOnce({
|
||||
body: {
|
||||
items: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'service-name',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await sut.fetchObjectsForService({
|
||||
const result = await sut.fetchObjectsForService({
|
||||
serviceId: 'some-service',
|
||||
clusterDetails: {
|
||||
name: 'cluster1',
|
||||
@@ -544,9 +452,33 @@ describe('KubernetesFetcher', () => {
|
||||
customResources: [],
|
||||
});
|
||||
|
||||
const mockCall = clientMock.listNamespacedCustomObject.mock.calls[0];
|
||||
const namespace = mockCall[2];
|
||||
expect(namespace).toBe('some-namespace');
|
||||
expect(result).toStrictEqual({
|
||||
errors: [],
|
||||
responses: [
|
||||
{
|
||||
type: 'pods',
|
||||
resources: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'pod-name',
|
||||
labels: { 'backstage.io/kubernetes-id': 'some-service' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'services',
|
||||
resources: [
|
||||
{
|
||||
metadata: {
|
||||
name: 'service-name',
|
||||
labels: { 'backstage.io/kubernetes-id': 'some-service' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user