add unit tests fetching pod metrics and clean up code
Signed-off-by: Mengnan Gong <namco1992@gmail.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-backend': minor
|
||||
'@backstage/plugin-kubernetes-common': minor
|
||||
'@backstage/plugin-kubernetes-common': patch
|
||||
---
|
||||
|
||||
The Kubernetes errors when fetching pod metrics are now captured and returned to the frontend.
|
||||
|
||||
Include the `PodStatusFetchResponse` into the `FetchResponse` union type. Now the method `fetchPodMetricsByNamespaces` accepts a set of namespaces and returns a `FetchResponseWrapper`, just like other public fetch methods in the fetcher.
|
||||
- **BREAKING** The method `fetchPodMetricsByNamespace` in the interface `KubernetesFetcher` is changed to `fetchPodMetricsByNamespaces`. It now accepts a set of namespace strings and returns `Promise<FetchResponseWrapper>`.
|
||||
- Add the `PodStatusFetchResponse` to the `FetchResponse` union type.
|
||||
- Add `NOT_FOUND` to the `KubernetesErrorTypes` union type, the HTTP error with status code 404 will be mapped to this error.
|
||||
|
||||
@@ -675,6 +675,82 @@ describe('getKubernetesObjectsByEntity', () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
it('retrieve objects for two clusters, one fails to fetch pod metrics', async () => {
|
||||
getClustersByEntity.mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
clusters: [
|
||||
{
|
||||
name: 'test-cluster',
|
||||
authProvider: 'serviceAccount',
|
||||
dashboardUrl: 'https://k8s.foo.coom',
|
||||
},
|
||||
{
|
||||
name: 'other-cluster',
|
||||
authProvider: 'google',
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
mockFetch(fetchObjectsForService);
|
||||
|
||||
// To simulate the partial failure, return a valid response for the first call,
|
||||
// and an error for the second call.
|
||||
fetchPodMetricsByNamespaces
|
||||
.mockImplementationOnce(
|
||||
(clusterDetails: ClusterDetails, namespaces: Set<string>) =>
|
||||
Promise.resolve(generatePodStatus(clusterDetails.name, namespaces)),
|
||||
)
|
||||
.mockResolvedValueOnce({
|
||||
errors: [
|
||||
{
|
||||
errorType: 'NOT_FOUND',
|
||||
resourcePath: '/some/path',
|
||||
statusCode: 404,
|
||||
},
|
||||
],
|
||||
responses: [],
|
||||
});
|
||||
|
||||
const sut = getKubernetesFanOutHandler([]);
|
||||
|
||||
const result = await sut.getKubernetesObjectsByEntity({
|
||||
entity,
|
||||
auth: {
|
||||
google: 'google_token_123',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getClustersByEntity.mock.calls.length).toBe(1);
|
||||
expect(fetchObjectsForService.mock.calls.length).toBe(2);
|
||||
expect(result).toStrictEqual({
|
||||
items: [
|
||||
{
|
||||
cluster: {
|
||||
dashboardUrl: 'https://k8s.foo.coom',
|
||||
name: 'test-cluster',
|
||||
},
|
||||
errors: [],
|
||||
podMetrics: [POD_METRICS_FIXTURE],
|
||||
resources: resourcesByCluster('test-cluster'),
|
||||
},
|
||||
{
|
||||
cluster: {
|
||||
name: 'other-cluster',
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
errorType: 'NOT_FOUND',
|
||||
resourcePath: '/some/path',
|
||||
statusCode: 404,
|
||||
},
|
||||
],
|
||||
podMetrics: [],
|
||||
resources: resourcesByCluster('other-cluster'),
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCustomResourcesByEntity', () => {
|
||||
|
||||
@@ -358,7 +358,7 @@ export class KubernetesFanOutHandler {
|
||||
namespaces,
|
||||
);
|
||||
|
||||
result.errors.concat(podMetrics.errors);
|
||||
result.errors.push(...podMetrics.errors);
|
||||
return [result, podMetrics.responses as PodStatusFetchResponse[]];
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CoreV1Api, topPods } from '@kubernetes/client-node';
|
||||
import { topPods } from '@kubernetes/client-node';
|
||||
import lodash, { Dictionary } from 'lodash';
|
||||
import { Logger } from 'winston';
|
||||
import {
|
||||
@@ -33,10 +33,6 @@ import {
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
import { KubernetesClientProvider } from './KubernetesClientProvider';
|
||||
|
||||
export interface Clients {
|
||||
core: CoreV1Api;
|
||||
}
|
||||
|
||||
export interface KubernetesClientBasedFetcherOptions {
|
||||
kubernetesClientProvider: KubernetesClientProvider;
|
||||
logger: Logger;
|
||||
@@ -66,6 +62,8 @@ const statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {
|
||||
return 'BAD_REQUEST';
|
||||
case 401:
|
||||
return 'UNAUTHORIZED_ERROR';
|
||||
case 404:
|
||||
return 'NOT_FOUND';
|
||||
case 500:
|
||||
return 'SYSTEM_ERROR';
|
||||
default:
|
||||
|
||||
@@ -179,6 +179,7 @@ export interface JobsFetchResponse {
|
||||
export type KubernetesErrorTypes =
|
||||
| 'BAD_REQUEST'
|
||||
| 'UNAUTHORIZED_ERROR'
|
||||
| 'NOT_FOUND'
|
||||
| 'SYSTEM_ERROR'
|
||||
| 'UNKNOWN_ERROR';
|
||||
|
||||
|
||||
@@ -233,6 +233,7 @@ export interface KubernetesFetchError {
|
||||
export type KubernetesErrorTypes =
|
||||
| 'BAD_REQUEST'
|
||||
| 'UNAUTHORIZED_ERROR'
|
||||
| 'NOT_FOUND'
|
||||
| 'SYSTEM_ERROR'
|
||||
| 'UNKNOWN_ERROR';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user