surface cluster title in ErrorReporting table
Signed-off-by: Jamie Klassen <jamie.klassen@broadcom.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes': patch
|
||||
'@backstage/plugin-kubernetes-react': patch
|
||||
---
|
||||
|
||||
The `ErrorReporting` component's cluster column now displays cluster titles when
|
||||
specified.
|
||||
@@ -176,11 +176,13 @@ export type ErrorPanelProps = {
|
||||
// @public (undocumented)
|
||||
export const ErrorReporting: ({
|
||||
detectedErrors,
|
||||
clusters,
|
||||
}: ErrorReportingProps) => React_3.JSX.Element;
|
||||
|
||||
// @public (undocumented)
|
||||
export type ErrorReportingProps = {
|
||||
detectedErrors: DetectedErrorsByCluster;
|
||||
clusters: ClusterAttributes[];
|
||||
};
|
||||
|
||||
// @public
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { DetectedError } from '@backstage/plugin-kubernetes-common';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { MatcherFunction, screen } from '@testing-library/react';
|
||||
import { ErrorReporting } from './ErrorReporting';
|
||||
|
||||
describe('ErrorReporting', () => {
|
||||
const matchTextContent =
|
||||
(text: string): MatcherFunction =>
|
||||
(_, node) =>
|
||||
node?.textContent?.includes(text) ?? false;
|
||||
|
||||
it('sorts errors by severity', async () => {
|
||||
await renderInTestApp(
|
||||
<ErrorReporting
|
||||
detectedErrors={
|
||||
new Map<string, DetectedError[]>([
|
||||
[
|
||||
'cluster',
|
||||
[
|
||||
{
|
||||
type: 'readiness-probe-taking-too-long',
|
||||
message:
|
||||
'The container my-container failed to start properly, but is not crashing',
|
||||
severity: 4,
|
||||
proposedFix: undefined,
|
||||
sourceRef: {
|
||||
name: 'my-pod',
|
||||
namespace: 'default',
|
||||
kind: 'Pod',
|
||||
apiGroup: 'v1',
|
||||
},
|
||||
occurrenceCount: 1,
|
||||
},
|
||||
{
|
||||
type: 'condition-message-present',
|
||||
message: 'some condition message',
|
||||
severity: 6,
|
||||
sourceRef: {
|
||||
name: 'my-deployment',
|
||||
namespace: 'default',
|
||||
kind: 'Deployment',
|
||||
apiGroup: 'apps/v1',
|
||||
},
|
||||
occurrenceCount: 1,
|
||||
},
|
||||
],
|
||||
],
|
||||
])
|
||||
}
|
||||
clusters={[{ name: 'cluster' }]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getAllByRole('row')).toEqual([
|
||||
expect.anything(),
|
||||
screen.getByText(matchTextContent('some condition message'), {
|
||||
selector: 'tr',
|
||||
}),
|
||||
screen.getByText(
|
||||
matchTextContent(
|
||||
'The container my-container failed to start properly, but is not crashing',
|
||||
),
|
||||
{ selector: 'tr' },
|
||||
),
|
||||
expect.anything(),
|
||||
]);
|
||||
});
|
||||
|
||||
it('displays cluster name', async () => {
|
||||
await renderInTestApp(
|
||||
<ErrorReporting
|
||||
detectedErrors={
|
||||
new Map<string, DetectedError[]>([
|
||||
[
|
||||
'my-cluster',
|
||||
[
|
||||
{
|
||||
type: 'condition-message-present',
|
||||
message: 'some condition message',
|
||||
severity: 6,
|
||||
sourceRef: {
|
||||
name: 'my-deployment',
|
||||
namespace: 'default',
|
||||
kind: 'Deployment',
|
||||
apiGroup: 'apps/v1',
|
||||
},
|
||||
occurrenceCount: 1,
|
||||
},
|
||||
],
|
||||
],
|
||||
])
|
||||
}
|
||||
clusters={[{ name: 'my-cluster' }]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByRole('cell', { name: 'my-cluster' }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('displays cluster title when specified', async () => {
|
||||
await renderInTestApp(
|
||||
<ErrorReporting
|
||||
detectedErrors={
|
||||
new Map<string, DetectedError[]>([
|
||||
[
|
||||
'my-cluster',
|
||||
[
|
||||
{
|
||||
type: 'condition-message-present',
|
||||
message: 'some condition message',
|
||||
severity: 6,
|
||||
sourceRef: {
|
||||
name: 'my-deployment',
|
||||
namespace: 'default',
|
||||
kind: 'Deployment',
|
||||
apiGroup: 'apps/v1',
|
||||
},
|
||||
occurrenceCount: 1,
|
||||
},
|
||||
],
|
||||
],
|
||||
])
|
||||
}
|
||||
clusters={[{ name: 'my-cluster', title: 'cluster-title' }]}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByRole('cell', { name: 'cluster-title' }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import {
|
||||
ClusterAttributes,
|
||||
DetectedError,
|
||||
DetectedErrorsByCluster,
|
||||
} from '@backstage/plugin-kubernetes-common';
|
||||
@@ -27,13 +28,14 @@ import { Table, TableColumn } from '@backstage/core-components';
|
||||
*/
|
||||
export type ErrorReportingProps = {
|
||||
detectedErrors: DetectedErrorsByCluster;
|
||||
clusters: ClusterAttributes[];
|
||||
};
|
||||
|
||||
const columns: TableColumn<Row>[] = [
|
||||
{
|
||||
title: 'cluster',
|
||||
width: '10%',
|
||||
render: (row: Row) => row.clusterName,
|
||||
render: (row: Row) => row.cluster.title || row.cluster.name,
|
||||
},
|
||||
{
|
||||
title: 'namespace',
|
||||
@@ -60,7 +62,7 @@ const columns: TableColumn<Row>[] = [
|
||||
];
|
||||
|
||||
interface Row {
|
||||
clusterName: string;
|
||||
cluster: ClusterAttributes;
|
||||
error: DetectedError;
|
||||
}
|
||||
|
||||
@@ -78,11 +80,14 @@ const sortBySeverity = (a: Row, b: Row) => {
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const ErrorReporting = ({ detectedErrors }: ErrorReportingProps) => {
|
||||
export const ErrorReporting = ({
|
||||
detectedErrors,
|
||||
clusters,
|
||||
}: ErrorReportingProps) => {
|
||||
const errors = Array.from(detectedErrors.entries())
|
||||
.flatMap(([clusterName, resourceErrors]) => {
|
||||
return resourceErrors.map(e => ({
|
||||
clusterName,
|
||||
cluster: clusters.find(c => c.name === clusterName)!,
|
||||
error: e,
|
||||
}));
|
||||
})
|
||||
|
||||
@@ -50,6 +50,8 @@ export const KubernetesContent = ({
|
||||
refreshIntervalMs,
|
||||
);
|
||||
|
||||
const clusters = kubernetesObjects?.items.map(item => item.cluster) ?? [];
|
||||
|
||||
const clustersWithErrors =
|
||||
kubernetesObjects?.items.filter(r => r.errors.length > 0) ?? [];
|
||||
|
||||
@@ -93,7 +95,10 @@ export const KubernetesContent = ({
|
||||
{kubernetesObjects && (
|
||||
<Grid container spacing={3} direction="column">
|
||||
<Grid item>
|
||||
<ErrorReporting detectedErrors={detectedErrors} />
|
||||
<ErrorReporting
|
||||
detectedErrors={detectedErrors}
|
||||
clusters={clusters}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="h3">Your Clusters</Typography>
|
||||
|
||||
Reference in New Issue
Block a user