|
1 | | -# OpenShift console plugin template |
2 | | - |
3 | | -This project is a minimal template for writing a new OpenShift Console dynamic |
4 | | -plugin. |
5 | | - |
6 | | -[Openshift console plugins](https://github.com/openshift/console/tree/main/frontend/packages/console-dynamic-plugin-sdk) |
7 | | -allow you to extend the [OpenShift web console](https://github.com/openshift/console) |
8 | | -at runtime, adding custom pages and other extensions. They are based on |
9 | | -[webpack module federation](https://webpack.js.org/concepts/module-federation/). |
10 | | -Plugins are registered with console using the `ConsolePlugin` custom resource |
11 | | -and enabled in the console operator config by a cluster administrator. |
12 | | - |
13 | | -The `main` branch of this repository contains an example plugin which works |
14 | | -with the latest version. To see an example of a plugin which works with an older |
15 | | -version, visit the appropriate `release-4.x` branch. |
16 | | - |
17 | | -[Node.js](https://nodejs.org/en/) and [yarn](https://yarnpkg.com) are required |
18 | | -to build and run the example. To run OpenShift console in a container, either |
19 | | -[Docker](https://www.docker.com) or [podman 3.2.0+](https://podman.io) and |
20 | | -[oc](https://console.redhat.com/openshift/downloads) are required. |
21 | | - |
22 | | -## Getting started |
23 | | - |
24 | | -> [!IMPORTANT] |
25 | | -> To use this template, **DO NOT FORK THIS REPOSITORY**! Click **Use this template**, then select |
26 | | -> [**Create a new repository**](https://github.com/new?template_name=console-plugin-template&template_owner=openshift) |
27 | | -> to create a new repository. |
28 | | -> |
29 | | ->  |
30 | | -> |
31 | | -> **Forking this repository** for purposes outside of contributing to this repository |
32 | | -> **will cause issues**, as users cannot have more than one fork of a template repository |
33 | | -> at a time. This could prevent future users from forking and contributing to your plugin. |
34 | | -> |
35 | | -> Your fork would also behave like a template repository, which might be confusing for |
36 | | -> contributiors, because it is not possible for repositories generated from a template |
37 | | -> repository to contribute back to the template. |
38 | | -
|
39 | | -After cloning your instantiated repository, you must update the plugin metadata, such as the |
40 | | -plugin name in the `consolePlugin` declaration of [package.json](package.json). |
| 1 | +# Cluster Update Console Plugin |
41 | 2 |
|
42 | | -```json |
43 | | -"consolePlugin": { |
44 | | - "name": "console-plugin-template", |
45 | | - "version": "0.0.1", |
46 | | - "displayName": "My Plugin", |
47 | | - "description": "Enjoy this shiny, new console plugin!", |
48 | | - "exposedModules": { |
49 | | - "ExamplePage": "./components/ExamplePage" |
50 | | - }, |
51 | | - "dependencies": { |
52 | | - "@console/pluginAPI": "*" |
53 | | - } |
54 | | -} |
55 | | -``` |
56 | | - |
57 | | -The template adds a single example page in the Home navigation section. The |
58 | | -extension is declared in the [console-extensions.json](console-extensions.json) |
59 | | -file and the React component is declared in |
60 | | -[src/components/ExamplePage.tsx](src/components/ExamplePage.tsx). |
61 | | - |
62 | | -You can run the plugin using a local development environment or build an image |
63 | | -to deploy it to a cluster. |
64 | | - |
65 | | -## Development |
66 | | - |
67 | | -### Option 1: Local |
| 3 | +An OpenShift Console dynamic plugin that provides an AI-driven cluster update experience. It integrates with [OpenShift Lightspeed](https://github.com/openshift/lightspeed-operator) proposals (via the `agentic.openshift.io` API) to assess upgrade readiness, show OLM operator compatibility, and let users approve or reject AI-generated update plans. |
68 | 4 |
|
69 | | -In one terminal window, run: |
| 5 | +## Features |
70 | 6 |
|
71 | | -1. `yarn install` |
72 | | -2. `yarn run start` |
| 7 | +- **Update Plan** — Shows the active AI-generated update proposal with risk assessment, readiness checks, OLM operator compatibility, API deprecation checks, and approve/deny actions. |
| 8 | +- **Active Update Plans** — Lists all non-terminal Lightspeed proposals. |
| 9 | +- **Update History** — Shows the ClusterVersion update history. |
| 10 | +- **Graceful Degradation** — Works without the Lightspeed Proposal CRD installed. The Update History tab is always functional; AI features show a warning banner when unavailable. |
73 | 11 |
|
74 | | -In another terminal window, run: |
| 12 | +## Prerequisites |
75 | 13 |
|
76 | | -1. `oc login` (requires [oc](https://console.redhat.com/openshift/downloads) and an [OpenShift cluster](https://console.redhat.com/openshift/create)) |
77 | | -2. `yarn run start-console` (requires [Docker](https://www.docker.com) or [podman 3.2.0+](https://podman.io)) |
| 14 | +- OpenShift 4.22+ (uses ConsolePlugin CRD v1 API, Console SDK 4.22) |
| 15 | +- [Node.js](https://nodejs.org/en/) 18+ and [Yarn](https://yarnpkg.com) 4.x |
| 16 | +- [oc](https://console.redhat.com/openshift/downloads) CLI |
| 17 | +- [Docker](https://www.docker.com) or [podman 3.2.0+](https://podman.io) (for running the console locally) |
78 | 18 |
|
79 | | -This will run the OpenShift console in a container connected to the cluster |
80 | | -you've logged into. The plugin HTTP server runs on port 9001 with CORS enabled. |
81 | | -Navigate to <http://localhost:9000/example> to see the running plugin. |
| 19 | +## Development |
82 | 20 |
|
83 | | -#### Running start-console with Apple silicon and podman |
| 21 | +### Local development |
84 | 22 |
|
85 | | -If you are using podman on a Mac with Apple silicon, `yarn run start-console` |
86 | | -might fail since it runs an amd64 image. You can workaround the problem with |
87 | | -[qemu-user-static](https://github.com/multiarch/qemu-user-static) by running |
88 | | -these commands: |
| 23 | +In one terminal: |
89 | 24 |
|
90 | 25 | ```bash |
91 | | -podman machine ssh |
92 | | -sudo -i |
93 | | -rpm-ostree install qemu-user-static |
94 | | -systemctl reboot |
| 26 | +yarn install |
| 27 | +yarn start |
95 | 28 | ``` |
96 | 29 |
|
97 | | -### Option 2: Docker + VSCode Remote Container |
98 | | - |
99 | | -Make sure the |
100 | | -[Remote Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) |
101 | | -extension is installed. This method uses Docker Compose where one container is |
102 | | -the OpenShift console and the second container is the plugin. It requires that |
103 | | -you have access to an existing OpenShift cluster. After the initial build, the |
104 | | -cached containers will help you start developing in seconds. |
105 | | - |
106 | | -1. Create a `dev.env` file inside the `.devcontainer` folder with the correct values for your cluster: |
| 30 | +In another terminal: |
107 | 31 |
|
108 | 32 | ```bash |
109 | | -OC_PLUGIN_NAME=console-plugin-template |
110 | | -OC_URL=https://api.example.com:6443 |
111 | | -OC_USER=kubeadmin |
112 | | -OC_PASS=<password> |
| 33 | +oc login # log into your OpenShift cluster |
| 34 | +yarn start-console |
113 | 35 | ``` |
114 | 36 |
|
115 | | -2. `(Ctrl+Shift+P) => Remote Containers: Open Folder in Container...` |
116 | | -3. `yarn run start` |
117 | | -4. Navigate to <http://localhost:9000/example> |
| 37 | +Navigate to <http://localhost:9000/administration/cluster-update>. |
118 | 38 |
|
119 | | -## Docker image |
| 39 | +The plugin dev server runs on port 9001 with CORS enabled. The console bridge runs on port 9000. |
120 | 40 |
|
121 | | -Before you can deploy your plugin on a cluster, you must build an image and |
122 | | -push it to an image registry. |
| 41 | +### Testing with mock data |
123 | 42 |
|
124 | | -1. Build the image: |
| 43 | +Without the Lightspeed agentic operator installed, Proposals have no analysis data. To test with mock data: |
125 | 44 |
|
126 | | - ```sh |
127 | | - docker build -t quay.io/my-repository/my-plugin:latest . |
| 45 | +1. Verify CVO-created Proposals exist: |
| 46 | + ```bash |
| 47 | + oc -n openshift-lightspeed get proposals.agentic.openshift.io |
128 | 48 | ``` |
129 | 49 |
|
130 | | -2. Run the image: |
131 | | - |
132 | | - ```sh |
133 | | - docker run -it --rm -d -p 9001:80 quay.io/my-repository/my-plugin:latest |
| 50 | +2. Get the Proposal UID: |
| 51 | + ```bash |
| 52 | + oc -n openshift-lightspeed get proposals.agentic.openshift.io -o custom-columns=NAME:.metadata.name,UID:.metadata.uid |
134 | 53 | ``` |
135 | 54 |
|
136 | | -3. Push the image: |
137 | | - |
138 | | - ```sh |
139 | | - docker push quay.io/my-repository/my-plugin:latest |
| 55 | +3. Update `mock-analysis-result.yaml` with the correct Proposal name and UID in `ownerReferences`, then apply: |
| 56 | + ```bash |
| 57 | + oc apply -f mock-analysis-result.yaml |
140 | 58 | ``` |
141 | 59 |
|
142 | | -NOTE: If you have a Mac with Apple silicon, you will need to add the flag |
143 | | -`--platform=linux/amd64` when building the image to target the correct platform |
144 | | -to run in-cluster. |
| 60 | +4. Patch the Proposal status to reference the AnalysisResult (see comments in `mock-analysis-result.yaml` for the full command). |
| 61 | + |
| 62 | +5. Patch the AnalysisResult status subresource with options data (the `status` field is a subresource, so `oc apply` won't set it — use `oc patch --subresource status`). |
145 | 63 |
|
146 | | -## Deployment on cluster |
| 64 | +### Code quality |
147 | 65 |
|
148 | | -A [Helm](https://helm.sh) chart is available to deploy the plugin to an OpenShift environment. |
| 66 | +```bash |
| 67 | +yarn lint # eslint + prettier + stylelint (with --fix) |
| 68 | +yarn test # Jest unit tests |
| 69 | +``` |
149 | 70 |
|
150 | | -The following Helm parameters are required: |
| 71 | +### Styling rules |
151 | 72 |
|
152 | | -`plugin.image`: The location of the image containing the plugin that was previously pushed |
| 73 | +The `.stylelintrc.yaml` enforces strict rules to prevent breaking console: |
153 | 74 |
|
154 | | -Additional parameters can be specified if desired. Consult the chart [values](charts/openshift-console-plugin/values.yaml) file for the full set of supported parameters. |
| 75 | +- No hex colors — use PatternFly CSS variables |
| 76 | +- No naked element selectors (`table`, `div`, etc.) |
| 77 | +- No `.pf-` or `.co-` prefixed classes |
| 78 | +- Prefix all custom classes with `cluster-update-plugin__` |
155 | 79 |
|
156 | | -### Installing the Helm Chart |
| 80 | +## Building and deploying |
157 | 81 |
|
158 | | -Install the chart using the name of the plugin as the Helm release name into a new namespace or an existing namespace as specified by the `plugin_console-plugin-template` parameter and providing the location of the image within the `plugin.image` parameter by using the following command: |
| 82 | +### Build the image |
159 | 83 |
|
160 | | -```shell |
161 | | -helm upgrade -i my-plugin charts/openshift-console-plugin -n my-namespace --create-namespace --set plugin.image=my-plugin-image-location |
| 84 | +```bash |
| 85 | +docker build -t quay.io/my-repository/cluster-update-console-plugin:latest . |
| 86 | +# For Apple Silicon: add --platform=linux/amd64 |
162 | 87 | ``` |
163 | 88 |
|
164 | | -NOTE: When deploying on OpenShift 4.10, it is recommended to add the parameter `--set plugin.securityContext.enabled=false` which will omit configurations related to Pod Security. |
| 89 | +### Deploy via Helm |
165 | 90 |
|
166 | | -NOTE: When defining i18n namespace, adhere `plugin__<name-of-the-plugin>` format. The name of the plugin should be extracted from the `consolePlugin` declaration within the [package.json](package.json) file. |
| 91 | +```bash |
| 92 | +helm upgrade -i cluster-update-console-plugin charts/openshift-console-plugin \ |
| 93 | + -n cluster-update-console-plugin \ |
| 94 | + --create-namespace \ |
| 95 | + --set plugin.image=quay.io/my-repository/cluster-update-console-plugin:latest |
| 96 | +``` |
167 | 97 |
|
168 | 98 | ## i18n |
169 | 99 |
|
170 | | -The plugin template demonstrates how you can translate messages in with [react-i18next](https://react.i18next.com/). The i18n namespace must match |
171 | | -the name of the `ConsolePlugin` resource with the `plugin__` prefix to avoid |
172 | | -naming conflicts. For example, the plugin template uses the |
173 | | -`plugin__console-plugin-template` namespace. You can use the `useTranslation` hook |
174 | | -with this namespace as follows: |
| 100 | +The i18n namespace is `plugin__cluster-update-console-plugin`. Use the `useTranslation` hook: |
175 | 101 |
|
176 | 102 | ```tsx |
177 | | -const Header: React.FC = () => { |
178 | | - const { t } = useTranslation('plugin__console-plugin-template'); |
179 | | - return <h1>{t('Hello, World!')}</h1>; |
180 | | -}; |
| 103 | +import { I18N_NAMESPACE } from '../utils/constants'; |
| 104 | +const { t } = useTranslation(I18N_NAMESPACE); |
181 | 105 | ``` |
182 | 106 |
|
183 | | -For labels in `console-extensions.json`, you can use the format |
184 | | -`%plugin__console-plugin-template~My Label%`. Console will replace the value with |
185 | | -the message for the current language from the `plugin__console-plugin-template` |
186 | | -namespace. For example: |
187 | | - |
| 107 | +For labels in `console-extensions.json`: |
188 | 108 | ```json |
189 | | - { |
190 | | - "type": "console.navigation/section", |
191 | | - "properties": { |
192 | | - "id": "admin-demo-section", |
193 | | - "perspective": "admin", |
194 | | - "name": "%plugin__console-plugin-template~Plugin Template%" |
195 | | - } |
196 | | - } |
| 109 | +"name": "%plugin__cluster-update-console-plugin~Cluster Update%" |
197 | 110 | ``` |
198 | 111 |
|
199 | | -Running `yarn i18n` updates the JSON files in the `locales` folder of the |
200 | | -plugin template when adding or changing messages. |
201 | | - |
202 | | -## Linting |
203 | | - |
204 | | -This project adds prettier, eslint, and stylelint. Linting can be run with |
205 | | -`yarn run lint`. |
206 | | - |
207 | | -The stylelint config disallows defining colors since these cause problems with dark |
208 | | -mode. Use [PatternFly semantic tokens](https://www.patternfly.org/tokens/all-patternfly-tokens) |
209 | | -for colors instead. |
210 | | - |
211 | | -The stylelint config also disallows naked element selectors like `table` and |
212 | | -`.pf-` or `.co-` prefixed classes. This prevents plugins from accidentally |
213 | | -overwriting default console styles, breaking the layout of existing pages. The |
214 | | -best practice is to prefix your CSS class names with your plugin name to avoid |
215 | | -conflicts. Please don't disable these rules without understanding how they can |
216 | | -break console styles! |
217 | | - |
218 | | -## Reporting |
219 | | - |
220 | | -Steps to generate reports |
221 | | - |
222 | | -1. In command prompt, navigate to root folder and execute the command `yarn run cypress-merge` |
223 | | -2. Then execute command `yarn run cypress-generate` |
224 | | -The cypress-report.html file is generated and should be in (/integration-tests/screenshots) directory. |
| 112 | +Run `yarn i18n` after adding or changing messages to update locale files. |
225 | 113 |
|
226 | 114 | ## References |
227 | 115 |
|
228 | | -- [Console Plugin SDK README](https://github.com/openshift/console/tree/main/frontend/packages/console-dynamic-plugin-sdk) |
229 | | -- [Customization Plugin Example](https://github.com/spadgett/console-customization-plugin) |
| 116 | +- [Console Plugin SDK](https://github.com/openshift/console/tree/main/frontend/packages/console-dynamic-plugin-sdk) |
| 117 | +- [PatternFly React](https://www.patternfly.org/get-started/develop) |
| 118 | +- [Lightspeed Operator](https://github.com/openshift/lightspeed-operator) |
230 | 119 | - [Dynamic Plugin Enhancement Proposal](https://github.com/openshift/enhancements/blob/master/enhancements/console/dynamic-plugins.md) |
0 commit comments