Skip to content

Commit

Permalink
feat(kiali): add KialiPage Component (janus-idp#1180)
Browse files Browse the repository at this point in the history
* feat(kiali): add KialiPage Component

* Set grid in overview cards for other namespaces
  • Loading branch information
aljesusg authored Feb 7, 2024
1 parent c2fe940 commit c91bcc3
Show file tree
Hide file tree
Showing 22 changed files with 555 additions and 262 deletions.
6 changes: 3 additions & 3 deletions plugins/kiali/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ async function main() {
apiRouter.use('/kiali', await kiali(kialiEnv));
```

6. Configure you `app-config.yaml` with kiali configuration
6. Configure you `app-config.local.yaml` with kiali configuration

```yaml
catalog:
Expand All @@ -103,7 +103,7 @@ catalog:

7. Add catalog

Add to locations in `app-config.yaml`
Add to locations in `app-config.local.yaml`

```yaml
locations:
Expand All @@ -116,7 +116,7 @@ locations:

### Token authentication

1. Set the parameters in app-config.yaml
1. Set the parameters in app-config.local.yaml

```yaml
catalog:
Expand Down
42 changes: 40 additions & 2 deletions plugins/kiali/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,53 @@ The Kiali plugin has the following capabilities:
***
#### Procedure
#### Setting up the OCM frontend package
1. Install the Kiali plugin using the following commands:
```console
yarn workspace app add @janus-idp/backstage-plugin-kiali
```
2. Enable the **Kiali** tab on the entity view page using the `packages/app/src/components/catalog/EntityPage.tsx` file:
2. Select the components that you want to use, such as:
- `KialiPage`: This is a standalone page or dashboard displaying all namespaces in the mesh. You can add `KialiPage` to `packages/app/src/App.tsx` file as follows:

```tsx title="packages/app/src/App.tsx"
/* highlight-add-next-line */
import { KialiPage } from '@janus-idp/backstage-plugin-kiali';
const routes = (
<FlatRoutes>
{/* ... */}
{/* highlight-add-next-line */}
<Route path="/kiali" element={<KialiPage />} />
</FlatRoutes>
);
```

You can also update navigation in `packages/app/src/components/Root/Root.tsx` as follows:

```tsx title="packages/app/src/components/Root/Root.tsx"
/* highlight-add-next-line */
import { KialiIcon } from '@janus-idp/backstage-plugin-kiali';
export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarPage>
<Sidebar>
<SidebarGroup label="Menu" icon={<MenuIcon />}>
{/* ... */}
{/* highlight-add-next-line */}
<SidebarItem icon={KialiIcon} to="kiali" text="Kiali" />
</SidebarGroup>
{/* ... */}
</Sidebar>
{children}
</SidebarPage>
);
```

- `EntityKialiContent`: This component is a React context provided for Kiali data, which is related to the current entity. The `EntityKialiContent` component is used to display any data on the React components mentioned in `packages/app/src/components/catalog/EntityPage.tsx`:

```tsx title="packages/app/src/components/catalog/EntityPage.tsx"
/* highlight-add-next-line */
Expand Down
22 changes: 22 additions & 0 deletions plugins/kiali/app-config.janus-idp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
dynamicPlugins:
frontend:
janus-idp.backstage-plugin-kiali:
appIcons:
- name: kialiIcon
importName: KialiIcon
dynamicRoutes:
- path: /kiali
importName: KialiPage
menuItem:
icon: kialiIcon
text: Kiali
mountPoints:
- config:
layout:
gridColumn: '1 / -1'
height: 75vh
if:
anyOf:
- hasAnnotation: backstage.io/kubernetes-namespace
importName: EntityKialiContent
mountPoint: entity.page.kiali/cards
59 changes: 47 additions & 12 deletions plugins/kiali/dev/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import React from 'react';

import { Entity } from '@backstage/catalog-model';
import { Content, Page } from '@backstage/core-components';
import { createDevApp } from '@backstage/dev-utils';
import { EntityProvider } from '@backstage/plugin-catalog-react';
import { TestApiProvider } from '@backstage/test-utils';

import { KialiPage, kialiPlugin } from '../src/plugin';
import { KialiHeader } from '../src/pages/Kiali/Header/KialiHeader';
import { KialiHeaderEntity } from '../src/pages/Kiali/Header/KialiHeaderEntity';
import { KialiEntity } from '../src/pages/Kiali/KialiEntity';
import { OverviewPage } from '../src/pages/Overview/OverviewPage';
import { kialiPlugin } from '../src/plugin';
import { KialiApi, kialiApiRef } from '../src/services/Api';
import { KialiProvider } from '../src/store/KialiProvider';
import { AuthInfo } from '../src/types/Auth';
Expand Down Expand Up @@ -237,24 +242,54 @@ class MockKialiClient implements KialiApi {
return true;
}
}
// @ts-expect-error
const MockProvider = ({ children }) => (
<TestApiProvider apis={[[kialiApiRef, new MockKialiClient()]]}>
<EntityProvider entity={mockEntity}>
<KialiProvider>{children}</KialiProvider>
</EntityProvider>
</TestApiProvider>
);

interface Props {
children: React.ReactNode;
isEntity?: boolean;
}

const MockProvider = (props: Props) => {
const content = (
<KialiProvider entity={mockEntity}>
<Page themeId="tool">
{!props.isEntity && <KialiHeader />}
<Content>
{props.isEntity && <KialiHeaderEntity />}
{props.children}
</Content>
</Page>
</KialiProvider>
);

const viewIfEntity = props.isEntity && (
<EntityProvider entity={mockEntity}>{content}</EntityProvider>
);

return (
<TestApiProvider apis={[[kialiApiRef, new MockKialiClient()]]}>
{viewIfEntity || content}
</TestApiProvider>
);
};

createDevApp()
.registerPlugin(kialiPlugin)
.addPage({
element: (
<MockProvider>
<KialiPage />
<OverviewPage />
</MockProvider>
),
title: 'Kiali Overview',
path: '/overview',
})
.addPage({
element: (
<MockProvider isEntity>
<KialiEntity />
</MockProvider>
),
title: 'Overview Page',
path: '/kiali/overview',
title: 'Kiali Entity',
path: '/kiali',
})
.render();
1 change: 1 addition & 0 deletions plugins/kiali/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@material-ui/core": "^4.9.13",
"@material-ui/icons": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.45",
"@mui/icons-material": "^5.15.8",
"@patternfly/patternfly": "^5.1.0",
"@patternfly/react-charts": "^7.1.1",
"@patternfly/react-core": "^5.1.1",
Expand Down
97 changes: 58 additions & 39 deletions plugins/kiali/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,63 +2,82 @@ import React from 'react';
import { Route, Routes } from 'react-router-dom';

import { Entity } from '@backstage/catalog-model';
import { MissingAnnotationEmptyState } from '@backstage/core-components';
import {
Content,
MissingAnnotationEmptyState,
Page,
} from '@backstage/core-components';
import { useEntity } from '@backstage/plugin-catalog-react';

import { Button } from '@material-ui/core';

import { KialiNoPath, KialiPage } from './pages/Kiali';
import { KialiNoPath } from './pages/Kiali';
import { KialiHeader } from './pages/Kiali/Header/KialiHeader';
import { KialiHeaderEntity } from './pages/Kiali/Header/KialiHeaderEntity';
import { KialiEntity } from './pages/Kiali/KialiEntity';
import { OverviewPage } from './pages/Overview/OverviewPage';
import { KialiProvider } from './store/KialiProvider';

export const KUBERNETES_ANNOTATION = 'backstage.io/kubernetes-id';
export const KUBERNETES_NAMESPACE = 'backstage.io/kubernetes-namespace';

export const KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION =
'backstage.io/kubernetes-label-selector';

export const isKubernetesAvailable = (entity: Entity) =>
Boolean(entity.metadata.annotations?.[KUBERNETES_ANNOTATION]) ||
Boolean(
entity.metadata.annotations?.[KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION],
const validateAnnotation = (entity: Entity) => {
return (
Boolean(entity.metadata.annotations?.[KUBERNETES_NAMESPACE]) ||
Boolean(entity.metadata.annotations?.[KUBERNETES_ANNOTATION]) ||
Boolean(
entity.metadata.annotations?.[KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION],
)
);
};

export const Router = () => {
const { entity } = useEntity();
const kubernetesAnnotationValue =
entity.metadata.annotations?.[KUBERNETES_ANNOTATION];

const kubernetesNamespaceValue =
entity.metadata.annotations?.[KUBERNETES_NAMESPACE];

const kubernetesLabelSelectorQueryAnnotationValue =
entity.metadata.annotations?.[KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION];
/*
Router for entity
*/

if (
kubernetesAnnotationValue ||
kubernetesNamespaceValue ||
kubernetesLabelSelectorQueryAnnotationValue
) {
export const EmbeddedRouter = () => {
const { entity } = useEntity();
if (!validateAnnotation(entity)) {
return (
<KialiProvider>
<Routes>
<Route path="/" element={<KialiPage />} />
<Route path="/overview" element={<KialiPage />} />
<Route path="*" element={<KialiNoPath />} />
</Routes>
</KialiProvider>
<>
<MissingAnnotationEmptyState annotation={KUBERNETES_ANNOTATION} />
<h1>
Or use a label selector query, which takes precedence over the
previous annotation.
</h1>
<Button variant="contained" color="primary" href="#">
Read Kiali Plugin Docs
</Button>
</>
);
}

return (
<>
<MissingAnnotationEmptyState annotation={KUBERNETES_ANNOTATION} />
<h1>
Or use a label selector query, which takes precedence over the previous
annotation.
</h1>
<Button variant="contained" color="primary" href="#">
Read Kiali Plugin Docs
</Button>
</>
<KialiProvider entity={entity}>
<KialiHeaderEntity />
<Routes>
<Route path="/" element={<KialiEntity />} />
<Route path="*" element={<KialiNoPath />} />
</Routes>
</KialiProvider>
);
};

export const Router = () => {
return (
<KialiProvider>
<Page themeId="tool">
<KialiHeader />
<Content>
<Routes>
<Route path="/" element={<OverviewPage />} />
<Route path="/overview" element={<OverviewPage />} />
<Route path="*" element={<KialiNoPath />} />
</Routes>
</Content>
</Page>
</KialiProvider>
);
};
8 changes: 4 additions & 4 deletions plugins/kiali/src/components/About/AboutUIModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ export const AboutUIModal = (props: AboutUIModalProps) => {
: `${externalService.name} URL`;
const additionalInfo = additionalComponentInfoContent(externalService);
return (
<div key={`component_${name}`}>
<Grid item xs={4}>
<>
<Grid item xs={8} key={`component_${name}`}>
{name}
</Grid>
<Grid item xs={8}>
<Grid item xs={4} key={`component_version_${name}`}>
{additionalInfo}
</Grid>
</div>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export const DebugInformation = (props: DebugInformationProps) => {
);

const kialiConfigCard = (
<CardTab label="Kiali Config" key="kialiConfig">
<CardTab label="Kiali Config" value="kialiConfig">
{copyClip}
</CardTab>
);
Expand Down
4 changes: 2 additions & 2 deletions plugins/kiali/src/components/MessageCenter/MessageCenter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const calculateMessageStatus = (state: KialiAppState) => {
);
};

export const MessageCenter = () => {
export const MessageCenter = (props: { color?: string }) => {
const kialiState = React.useContext(KialiContext) as KialiAppState;
const [isOpen, toggleDrawer] = React.useState(false);
const messageCenterStatus = calculateMessageStatus(kialiState);
Expand All @@ -99,7 +99,7 @@ export const MessageCenter = () => {
}
color={messageCenterStatus.badgeDanger ? 'error' : 'primary'}
>
<KialiIcon.Bell className={bell} />
<KialiIcon.Bell className={bell} color={`${props.color}`} />
</Badge>
</Button>
<Drawer anchor="right" open={isOpen} onClose={() => toggleDrawer(false)}>
Expand Down
4 changes: 3 additions & 1 deletion plugins/kiali/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { kialiPlugin, EntityKialiContent } from './plugin';
export { kialiPlugin, EntityKialiContent, KialiPage } from './plugin';

export { default as KialiIcon } from '@mui/icons-material/Troubleshoot';
Loading

0 comments on commit c91bcc3

Please sign in to comment.