Provides webpack ConsoleRemotePlugin used to build all dynamic plugin assets.
Based on the concept of webpack module federation,
dynamic plugins are loaded and interpreted from remote sources at runtime. The standard way to deliver
and expose dynamic plugins to Console is through OLM operators.
Dynamic plugins are decoupled from the Console application, which means both plugins and Console can be
released, installed and upgraded independently from each other. To ensure compatibility with Console and
other plugins, each plugin must declare its dependencies using semantic version
ranges.
Example project structure:
```
dynamic-demo-plugin/
├── src/
├── console-extensions.json
├── package.json
├── tsconfig.json
└── webpack.config.ts
_[Extension Documentation][console-doc-extensions]_ - Detailed documentation of all available Console
extension points.
_[API Documentation][console-doc-api]_ - Detailed documentation of React components, hooks and other APIs
provided by Console to its dynamic plugins.
_[OpenShift Console Dynamic Plugins feature page][console-doc-feature-page]_ - A high-level overview of
dynamic plugins in relation to OLM operators and cluster administration.
If you're new to dynamic plugins, we suggest to clone the [Console plugin template][console-plugin-template]
repo and follow its instructions on setting up a local plugin development environment. We recommend running
the Console application with a container image to avoid having to build Console locally.
The CronTab plugin is a sample plugin that uses the
CronTab Custom Resource Definition (CRD) from
Kubernetes documentation
and implements basic CRD operations such as creating, editing and deleting.
The [Console demo plugin][console-demo-plugin] located in the Console repo is primarily meant for testing
the current Console plugin SDK features.
Here is a list of real world dynamic plugins that may serve as a further reference point:
| Plugin Name | Git Repo |
| ---------------------------------------------------------- | ---------------------------------------------------------------------- |
| kubevirt-plugin (KubeVirt) | https://github.com/kubevirt-ui/kubevirt-plugin |networking-console-plugin
| (OpenShift Networking) | https://github.com/openshift/networking-console-plugin |netobserv-plugin
| (Network Observability) | https://github.com/netobserv/network-observability-console-plugin |odf-console
| (OpenShift Data Foundation) | https://github.com/red-hat-storage/odf-console/tree/master/plugins/odf |odf-multicluster-console
| (ODF MultiCluster Orchestrator) | https://github.com/red-hat-storage/odf-console/tree/master/plugins/mco |pipelines-console-plugin
| (OpenShift Pipelines) | https://github.com/openshift-pipelines/console-plugin |acm
| (Red Hat Advanced Cluster Management) | https://github.com/stolostron/console/tree/main/frontend/plugins/acm |mce
| (MultiCluster Engine for Kubernetes) | https://github.com/stolostron/console/tree/main/frontend/plugins/mce |ossmconsole
| (OpenShift Service Mesh) | https://github.com/kiali/openshift-servicemesh-plugin |kuadrant-console-plugin
| (Red Hat Connectivity Link) | https://github.com/kuadrant/kuadrant-console-plugin |
There's also the Cat Facts Operator which serves
as a reference point for writing an OLM operator that ships with its own Console dynamic plugin.
| Package Name | Description |
| -------------------------------------------------- | -------------------------------------------------------------------------------- |
| @openshift-console/dynamic-plugin-sdk ★ | Provides core APIs, types and utilities used by dynamic plugins at runtime. |@openshift-console/dynamic-plugin-sdk-webpack
| ★ | Provides webpack ConsoleRemotePlugin used to build all dynamic plugin assets. |@openshift-console/dynamic-plugin-sdk-internal
| | Internal package exposing additional Console code. |@openshift-console/plugin-shared
| | Provides reusable components and utility functions to build OCP dynamic plugins. |
Packages marked with ★ provide essential plugin APIs with backwards compatibility. Other packages may be
used with multiple versions of OpenShift Console but don't provide any backwards compatibility guarantees.
Console plugin SDK packages follow a semver scheme where the major and minor version number indicates
the earliest supported OCP Console version, and the patch version number indicates the release of that
particular package.
During development, we will publish prerelease versions of plugin SDK packages, e.g. 4.19.0-prerelease.1.4.19.0
Once the given Console version is released (GA), we will publish corresponding plugin SDK packages without
the prerelease tag, e.g. .
For older 1.x plugin SDK packages, refer to the following version compatibility table:
| Console Version | SDK Package | Last Package Version |
| --------------- | ----------------------------------------------- | -------------------- |
| 4.17.x | @openshift-console/dynamic-plugin-sdk | 1.6.0 |@openshift-console/dynamic-plugin-sdk-webpack
| | | 1.2.0 |@openshift-console/dynamic-plugin-sdk
| 4.16.x | | 1.4.0 |@openshift-console/dynamic-plugin-sdk-webpack
| | | 1.1.1 |@openshift-console/dynamic-plugin-sdk
| 4.15.x | | 1.0.0 |@openshift-console/dynamic-plugin-sdk-webpack
| | | 1.0.2 |@openshift-console/dynamic-plugin-sdk
| 4.14.x | | 0.0.21 |@openshift-console/dynamic-plugin-sdk-webpack
| | | 0.0.11 |@openshift-console/dynamic-plugin-sdk
| 4.13.x | | 0.0.19 |@openshift-console/dynamic-plugin-sdk-webpack
| | | 0.0.9 |@openshift-console/dynamic-plugin-sdk
| 4.12.x | | 0.0.18 |@openshift-console/dynamic-plugin-sdk-webpack
| | | 0.0.9 |
Note: this table includes Console versions which currently receive technical support, as per
Red Hat OpenShift Container Platform Life Cycle Policy.
Each Console version supports specific version(s) of PatternFly in terms
of CSS styling. This table will help align compatible versions of PatternFly to versions of the OpenShift
Console.
| Console Version | PatternFly Versions | Notes |
| --------------- | ------------------- | ------------------------------------- |
| 4.19.x | 6.x + 5.x | New dynamic plugins should use PF 6.x |
| 4.15.x - 4.18.x | 5.x + 4.x | New dynamic plugins should use PF 5.x |
| 4.12.x - 4.14.x | 4.x | |
Console application is responsible for loading base styles for all supported PatternFly version(s).
Plugins should only include styles that are specific to their user interfaces to be evaluated on
top of base PatternFly styles. Avoid importing styles such as @patternfly/react-styles/*/.css@patternfly/patternfly
or any styles from package in your plugin.
Plugins should use PatternFly components and styles for a consistent user interface. Refer to the relevant
release notes for more details on PatternFly versions supported by each Console version.
Console is configured to share specific modules with its dynamic plugins.
The following shared modules are provided by Console, without plugins providing their own fallback:
- @openshift-console/dynamic-plugin-sdk@openshift-console/dynamic-plugin-sdk-internal
- @patternfly/react-topology
- react
- react-i18next
- react-redux
- react-router
- react-router-dom
- react-router-dom-v5-compat
- redux
- redux-thunk
-
Any shared modules provided by Console without plugin provided fallback are listed as dependenciespackage.json
in the manifest of @openshift-console/dynamic-plugin-sdk package.
Refer to the CHANGELOG.md in @openshift-console/dynamic-plugin-sdk and @openshift-console/dynamic-plugin-sdk-webpack
for each release for package-specific changes.
For general changes made to Console's API, such as changes to shared modules, refer to the relevant
release notes.
Console application uses Content Security Policy
(CSP) to detect and mitigate certain types of attacks. By default, the list of allowed
CSP sources
includes the document origin 'self' and Console webpack dev server when running off-cluster.
All dynamic plugin assets _should_ be loaded using /api/plugins/ Bridge endpoint which'self'
matches the CSP source for all Console assets served via Bridge.
Refer to BuildCSPDirectives function inpkg/utils/utils.go
for details on the current Console CSP implementation.
Refer to [Dynamic Plugins feature page][console-doc-feature-page] section on Content Security Policy
for more details.
Older versions of webpack ConsoleRemotePlugin assumed that the plugin metadata is specified viaconsolePlugin object within the package.json file, for example:
`jsonc`
{
"name": "dynamic-demo-plugin",
"version": "0.0.0",
// scripts, dependencies, devDependencies, ...
"consolePlugin": {
"name": "console-demo-plugin",
"version": "0.0.0",
"displayName": "Console Demo Plugin",
"description": "Plasma reactors online. Initiating hyper drive.",
"exposedModules": {
"barUtils": "./utils/bar"
},
"dependencies": {
"@console/pluginAPI": "~4.19.0"
}
}
}
Newer versions of webpack ConsoleRemotePlugin allow passing the plugin metadata directly as an
object, for example:
`ts`
new ConsoleRemotePlugin({
pluginMetadata: {
/ same metadata like above /
},
});
name serves as the plugin's unique identifier. Its value should be the same as metadata.nameConsolePlugin
of the corresponding resource on the cluster. Therefore, it must be a valid
DNS subdomain name.
version must be semver compliant version string.
Dynamic plugins can expose modules representing plugin code that can be referenced, loaded and executed
at runtime. A separate webpack chunk is generated for
each entry in the exposedModules object. Exposed modules are resolved relative to the plugin's webpackcontext option.
Dynamic plugins might declare dependency on specific Console versions and other plugins. This metadata
field is similar to dependencies in the package.json file with values represented as semver ranges.
The @console/pluginAPI dependency is optional and refers to Console versions this dynamic plugin is
meant to be compatible with. It is matched against the actual Console release version, as provided by
the Console operator.
The dependencies object might also refer to other dynamic plugins that are required for this plugin to
work correctly. Such other plugins will be loaded before loading this plugin.
Plugins might also use the optionalDependencies object to support use cases, such as plugin A integratingdependencies
with plugin B while still allowing plugin A to be loaded when plugin B is not enabled on the cluster.
This object has the same structure as object.
`jsonc`
{
// ...
"consolePlugin": {
// ...
"dependencies": {
// If foo-plugin is available, load it before loading this plugin.
// If foo-plugin is NOT available, this plugin will fail to load.
"foo-plugin": "~1.1.0",
},
"optionalDependencies": {
// If bar-plugin is available, load it before loading this plugin.
// If bar-plugin is NOT available, load this plugin regardless.
"bar-plugin": "^2.3.4"
},
}
}
For dependencies where the version string might include a semver pre-release
identifier, adapt your semver range constraint (dependency value) to include the relevant pre-release
prefix, e.g. use ~4.11.0-0.ci when targeting pre-release versions such as 4.11.0-0.ci-1234.
Older versions of webpack ConsoleRemotePlugin assumed that the list of extensions contributed by theconsole-extensions.json
plugin is specified via the file, for example:
`jsonc`
// This file is parsed as JSONC (JSON with Comments)
[
{
"type": "console.flag",
"properties": {
"handler": { "$codeRef": "barUtils.testHandler" }
}
},
{
"type": "console.flag/model",
"properties": {
"flag": "EXAMPLE",
"model": {
"group": "kubevirt.io",
"version": "v1alpha3",
"kind": "ExampleModel"
}
}
}
]
Newer versions of webpack ConsoleRemotePlugin allow passing the extension list directly as an array
of objects, for example:
`ts`
new ConsoleRemotePlugin({
extensions: [
/ same extensions like above /
],
});
Each extension a single instance of extending the Console application's functionality. Extensions are
declarative and expressed as plain static objects.
Extension type determines the kind of extension to perform, while any data and/or code necessary toproperties
interpret such extensions are declared through their .
Extensions may contain code references pointing to specific modules exposed by the plugin. For example:
- { $codeRef: 'barUtils' } - refers to default export of barUtils module{ $codeRef: 'barUtils.testHandler' }
- - refers to testHandler export of barUtils module
When loading dynamic plugins, all encoded code references { $codeRef: string } are transformed into() => Promise
functions used to load the referenced objects on demand. Only the plugin's exposedexposedModules
modules (i.e. the keys of object) may be used in code references.
Dynamic plugins _must_ be built with webpack in order for their modules to
seamlessly integrate with Console application at runtime. Use webpack version 5+ which includes native
support for module federation.
All dynamic plugin assets are generated via webpack ConsoleRemotePlugin.
`ts
import { ConsoleRemotePlugin } from '@openshift-console/dynamic-plugin-sdk-webpack';
import { Configuration } from 'webpack';
const config: Configuration = {
entry: {}, // Plugin container entry is generated by DynamicRemotePlugin
plugins: [new ConsoleRemotePlugin()],
// ... rest of webpack configuration
};
export default config;
`
Refer to ConsoleRemotePluginOptions type for details on supported Console plugin build options.
Building the above example plugin produces the following assets:
``
dynamic-demo-plugin/dist/
├── exposed-barUtils-chunk.js
├── plugin-entry.js
└── plugin-manifest.json
plugin-manifest.json is the dynamic plugin manifest. It contains both plugin metadata and extension
declarations to be loaded and interpreted by Console at runtime. This is the first plugin asset loaded
by Console.
plugin-entry.js is the
webpack container entry chunk.
It provides access to specific modules exposed by the plugin. It's loaded right after the plugin manifest.
exposed-barUtils-chunk.js is the generated webpack chunk for barUtils exposed module. It's loadedplugin-entry.js
via the plugin entry chunk () when needed.
Plugins may also include other assets, such as JSON localization files that follow the general pattern
locales/ or static images referenced from the plugin code.
Dynamic plugins are deployed as workloads on the cluster. Each plugin deployment should include a web
server that hosts the generated assets of the given plugin.
Console Bridge server adds X-Content-Type-Options: nosniff HTTP response header to all plugin asset
requests for added security. Web browsers that comply with this security header will block