Skip to content

Commit

Permalink
fix(openshift-image-registry): fix #596: Add mock data for test page …
Browse files Browse the repository at this point in the history
…and cleanup some small code smells (#1024)

fix #596: Add mock data for test page and cleanup some small code smells
christoph-jerolimov authored Dec 21, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent d3fdcdf commit 39f7351
Showing 9 changed files with 1,926 additions and 34 deletions.
26 changes: 25 additions & 1 deletion plugins/openshift-image-registry/README.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,30 @@ The OpenShift Image Registry plugin displays all ImageStreams in an Openshift cl

## For administrators

### Prerequisites

The OpenShift Image Registry plugin requires read access to **_all_** `ImageStreams` and `ImageStreamTags` on a cluster. (Currently only a single cluster is supported.)

You can create a `ServiceAccount`, `ClusterRole` and `ClusterRoleBinding` with this commands.

Please notice that the ServiceAccount will be created in your current namespace while the `ClusterRole` and `ClusterRoleBinding` giving access to all namespaces are cluster-wide resources.

Additional information on these commands could be found in the [OpenShift Container Platform authentication and authorization documentation](https://docs.openshift.com/container-platform/latest/authentication/index.html).

```console
oc create serviceaccount janus-idp-openshift-image-registry-reader

oc create clusterrole janus-idp-openshift-image-registry-reader --verb=get,watch,list --resource=imagestreams --resource=imagestreamtags

oc adm policy add-cluster-role-to-user janus-idp-openshift-image-registry-reader -z janus-idp-openshift-image-registry-reader
```

And finally you can use this command to create a token that is valid for one week:

```console
oc create token --duration=168h janus-idp-openshift-image-registry-reader
```

### Installation

Run the following command to install the OpenShift Image Registry plugin:
@@ -46,7 +70,7 @@ yarn workspace app add @janus-idp/backstage-plugin-openshift-image-registry
to="openshift-image-registry"
text="Image Registry"
/>
;{/* highlight-add-end */}
{/* highlight-add-end */}
</SidebarGroup>
{/* ... */}
</Sidebar>
84 changes: 82 additions & 2 deletions plugins/openshift-image-registry/dev/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,97 @@
import React from 'react';

import { createDevApp } from '@backstage/dev-utils';
import { TestApiProvider } from '@backstage/test-utils';

import {
openshiftImageRegistryApiRef,
OpenshiftImageRegistryApiV1,
} from '../src/api';
import {
OpenshiftImageRegistryPage,
openshiftImageRegistryPlugin,
} from '../src/plugin';
// Contains just the openshift namespace for now
import namespaces from './namespaces.json';
// Extracted from an OpenShift 4.13 cluster, reduced to Go, Java, Node.js and Python entries
// oc get -n openshift \
// imagestream/golang \
// imagestream/java \
// imagestream/nodejs \
// imagestream/python \
// -o json | jq . \
// > plugins/openshift-image-registry/dev/openshift-imagestreams.json
import openshiftImageStreams from './openshift-imagestreams.json';
// The origin list view doesn't contain all neccessary infomation, so this list view
// is build from three API calls to match the data in openshift-imagestreams.json
//
// oc get -n openshift \
// imagestreamtag/golang:1.18-ubi7 \
// imagestreamtag/java:11 \
// imagestreamtag/nodejs:14-ubi7 \
// imagestreamtag/python:2.7-ubi8 \
// -o json | jq . \
// > plugins/openshift-image-registry/dev/openshift-imagestreamtags.json
import openshiftImageStreamTags from './openshift-imagestreamtags.json';

class MockOpenshiftImageRegistryApi implements OpenshiftImageRegistryApiV1 {
async getAllImageStreams(): Promise<any> {
return openshiftImageStreams.items;
}
async getImageStreams(ns: string): Promise<any> {
return openshiftImageStreams.items.filter(
item => item.metadata.namespace === ns,
);
}
async getImageStream(ns: string, imageName: string): Promise<any> {
return openshiftImageStreams.items.find(
item =>
item.metadata.namespace === ns && item.metadata.name === imageName,
);
}
async getImageStreamTags(ns: string, imageName: string): Promise<any> {
if (imageName.includes(':')) {
return openshiftImageStreamTags.items.find(
item =>
item.metadata.namespace === ns && item.metadata.name === imageName,
);
}
return openshiftImageStreamTags.items.find(
item =>
item.metadata.namespace === ns &&
(item.metadata.name === imageName ||
item.metadata.name.startsWith(`${imageName}:`)),
);
}
async getImageStreamTag(
ns: string,
imageName: string,
tag: string,
): Promise<any> {
return openshiftImageStreamTags.items.find(
item =>
item.metadata.namespace === ns &&
item.metadata.name === `${imageName}:${tag}`,
);
}
async getNamespaces(): Promise<any> {
return namespaces.items;
}
}

createDevApp()
.registerPlugin(openshiftImageRegistryPlugin)
.addPage({
element: <OpenshiftImageRegistryPage />,
title: 'Root Page',
element: (
<TestApiProvider
apis={[
[openshiftImageRegistryApiRef, new MockOpenshiftImageRegistryApi()],
]}
>
<OpenshiftImageRegistryPage />
</TestApiProvider>
),
title: 'Image Registry',
path: '/openshift-image-registry',
})
.render();
26 changes: 26 additions & 0 deletions plugins/openshift-image-registry/dev/namespaces.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"kind": "NamespaceList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "81626349"
},
"items": [
{
"metadata": {
"name": "openshift",
"uid": "e9c1249f-b300-4b43-8c10-cd8473280844",
"resourceVersion": "75916512",
"creationTimestamp": "2023-07-26T18:44:09Z",
"labels": {
"kubernetes.io/metadata.name": "openshift"
}
},
"spec": {
"finalizers": ["kubernetes"]
},
"status": {
"phase": "Active"
}
}
]
}
1,111 changes: 1,111 additions & 0 deletions plugins/openshift-image-registry/dev/openshift-imagestreams.json

Large diffs are not rendered by default.

650 changes: 650 additions & 0 deletions plugins/openshift-image-registry/dev/openshift-imagestreamtags.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/openshift-image-registry/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@ export class OpenshiftImageRegistryApiClient

private async getBaseUrl() {
const proxyPath =
this.configApi.getOptionalString('openshiftImageRegistry.proxyPath') ||
this.configApi.getOptionalString('openshiftImageRegistry.proxyPath') ??
DEFAULT_PROXY_PATH;
return `${await this.discoveryApi.getBaseUrl('proxy')}${proxyPath}`;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';

import { CopyTextButton, MarkdownContent } from '@backstage/core-components';
import { BackstageTheme } from '@backstage/theme';

import {
Box,
@@ -11,13 +10,14 @@ import {
IconButton,
Input,
makeStyles,
Theme,
Typography,
} from '@material-ui/core';
import Close from '@material-ui/icons/Close';

import { ImageStreamMetadata } from '../../types';

const useDrawerStyles = makeStyles<BackstageTheme>(theme =>
const useDrawerStyles = makeStyles<Theme>(theme =>
createStyles({
paper: {
width: '40%',
@@ -27,7 +27,7 @@ const useDrawerStyles = makeStyles<BackstageTheme>(theme =>
}),
);

const useDrawerContentStyles = makeStyles<BackstageTheme>(theme =>
const useDrawerContentStyles = makeStyles<Theme>(theme =>
createStyles({
header: {
display: 'flex',
@@ -56,23 +56,23 @@ const useDrawerContentStyles = makeStyles<BackstageTheme>(theme =>
);

type OcirImageSidebarProps = {
isOpen: boolean;
toggleDrawer: React.Dispatch<React.SetStateAction<boolean>>;
open: boolean;
onClose: () => void;
imageStream: ImageStreamMetadata;
};

export const OcirImageSidebar = ({
isOpen,
toggleDrawer,
open,
onClose,
imageStream,
}: OcirImageSidebarProps) => {
const classes = useDrawerStyles();
const contentClasses = useDrawerContentStyles();
return (
<Drawer
anchor="right"
open={isOpen}
onClose={() => toggleDrawer(false)}
open={open}
onClose={onClose}
classes={{
paper: classes.paper,
}}
@@ -83,7 +83,7 @@ export const OcirImageSidebar = ({
<IconButton
key="dismiss"
title="Close the drawer"
onClick={() => toggleDrawer(false)}
onClick={onClose}
color="inherit"
>
<Close className={contentClasses.icon} />
@@ -95,7 +95,7 @@ export const OcirImageSidebar = ({
Description
</Typography>
<MarkdownContent
content={imageStream.description || 'N/A'}
content={imageStream.description ?? 'N/A'}
className={contentClasses.description}
/>
</Box>
@@ -112,15 +112,15 @@ export const OcirImageSidebar = ({
Version
</Typography>
<span className={contentClasses.description}>
{imageStream.version || 'N/A'}
{imageStream.version ?? 'N/A'}
</span>
</Box>
<Box>
<Typography variant="body2" className={contentClasses.label}>
Size
</Typography>
<span className={contentClasses.description}>
{imageStream.size || 'N/A'}
{imageStream.size ?? 'N/A'}
</span>
</Box>
<Box>
@@ -132,8 +132,8 @@ export const OcirImageSidebar = ({
Tags
</Typography>
{imageStream.tags?.length
? imageStream.tags.map((tag: string, i: number) => (
<Chip size="small" label={tag} key={i} />
? imageStream.tags.map((tag: string) => (
<Chip key={tag} size="small" label={tag} />
))
: 'N/A'}
</Box>
Original file line number Diff line number Diff line change
@@ -5,7 +5,6 @@ import {
LinkButton,
MarkdownContent,
} from '@backstage/core-components';
import { BackstageTheme } from '@backstage/theme';

import {
Box,
@@ -15,12 +14,13 @@ import {
CardMedia,
Chip,
makeStyles,
Theme,
Typography,
} from '@material-ui/core';

import { ImageStreamMetadata } from '../../types';

const useStyles = makeStyles<BackstageTheme>(theme => ({
const useStyles = makeStyles<Theme>(theme => ({
label: {
color: theme.palette.text.secondary,
textTransform: 'uppercase',
@@ -39,12 +39,12 @@ const useStyles = makeStyles<BackstageTheme>(theme => ({

type OcirImagesCardProps = {
imageStream: ImageStreamMetadata;
openSidebar: (imageStream: ImageStreamMetadata) => void;
onImageStreamSelected: (imageStream: ImageStreamMetadata) => void;
};

export const OcirImagesCard = ({
imageStream,
openSidebar,
onImageStreamSelected,
}: OcirImagesCardProps) => {
const classes = useStyles();

@@ -65,7 +65,7 @@ export const OcirImagesCard = ({
Description
</Typography>
<MarkdownContent
content={imageStream.description || 'N/A'}
content={imageStream.description ?? 'N/A'}
className={classes.description}
/>
</Box>
@@ -86,8 +86,8 @@ export const OcirImagesCard = ({
Tags
</Typography>
{imageStream.tags?.length
? imageStream.tags.map((tag: string, i: number) => (
<Chip size="small" label={tag} key={i} />
? imageStream.tags.map((tag: string) => (
<Chip key={tag} size="small" label={tag} />
))
: 'N/A'}
</Box>
@@ -96,7 +96,7 @@ export const OcirImagesCard = ({
<LinkButton
color="primary"
to=""
onClick={() => openSidebar(imageStream)}
onClick={() => onImageStreamSelected(imageStream)}
>
Open
</LinkButton>
Original file line number Diff line number Diff line change
@@ -12,19 +12,20 @@ type OcirImagesCardsProps = {
};

export const OcirImagesCards = ({ imageStreams }: OcirImagesCardsProps) => {
const [isOpen, toggleDrawer] = React.useState<boolean>(false);
const [isOpen, setIsOpen] = React.useState<boolean>(false);
const [activeImageStream, setActiveImageStream] =
React.useState<ImageStreamMetadata>();
const [filteredImageStreams, setFilteredImageStreams] = React.useState<
ImageStreamMetadata[] | undefined
>();

const imageStreamsList = filteredImageStreams || imageStreams;
const imageStreamsList = filteredImageStreams ?? imageStreams;

const handleOpen = React.useCallback(imageStream => {
const handleImageStreamSelected = React.useCallback(imageStream => {
setActiveImageStream(imageStream);
toggleDrawer(true);
setIsOpen(true);
}, []);
const handleClose = React.useCallback(() => setIsOpen(false), [setIsOpen]);

return (
<>
@@ -39,14 +40,14 @@ export const OcirImagesCards = ({ imageStreams }: OcirImagesCardsProps) => {
<OcirImagesCard
key={imageStream.uid}
imageStream={imageStream}
openSidebar={handleOpen}
onImageStreamSelected={handleImageStreamSelected}
/>
))}
</ItemCardGrid>
{activeImageStream && (
<OcirImageSidebar
isOpen={isOpen}
toggleDrawer={toggleDrawer}
open={isOpen}
onClose={handleClose}
imageStream={activeImageStream}
/>
)}

0 comments on commit 39f7351

Please sign in to comment.