Skip to content

Latest commit

 

History

History

dynamic-demo-plugin

OpenShift Console Demo Plugin

This project emulates a standalone repository hosting a sample dynamic plugin for OpenShift Console.

It is meant to serve as a reference for Console plugin developers and for testing dynamic plugin capabilities via end-to-end tests.

Local development

  1. yarn --cwd ../frontend install to install dependant frontend resources
  2. yarn install to install plugin dependencies
  3. yarn build to build the plugin, generating output to dist directory
  4. yarn http-server to start an HTTP server hosting the generated assets
Starting up http-server, serving ./dist
Available on:
  https://127.0.0.1:9001
  https://192.168.1.190:9001
  https://10.40.192.80:9001
Hit CTRL-C to stop the server

The server runs on port 9001 with caching disabled and CORS enabled. Additional server options can be passed to the script, for example:

yarn http-server -a 127.0.0.1

In another terminal window, run:

  1. oc login (requires oc and an OpenShift cluster)
  2. yarn run start-console (requires Docker or podman 3.2.0+)

This will run the OpenShift console in a container connected to the cluster you've logged into. The plugin HTTP server runs on port 9001 with CORS enabled. Navigate to https://localhost:9000 to see the running plugin.

Running start-console with Apple silicon and podman

If you are using podman on a Mac with Apple silicon, yarn run start-console might fail since it runs an amd64 image. You can workaround the problem with qemu-user-static by running these commands:

podman machine ssh
sudo -i
rpm-ostree install qemu-user-static
systemctl reboot

See the plugin development section in Console Dynamic Plugins README for details on how to run Bridge using local plugins.

Deployment on cluster

Console dynamic plugins are supposed to be deployed via OLM operators. In case of demo plugin, we just apply a minimal OpenShift manifest which adds the necessary resources.

oc apply -f oc-manifest.yaml

Note that the Service exposing the HTTP server is annotated to have a signed service serving certificate generated and mounted into the image. This allows us to run the server with HTTP/TLS enabled, using a trusted CA certificate.

Enabling the plugin

Once deployed on the cluster, demo plugin must be enabled before it can be loaded by Console.

To enable the plugin manually, edit Console operator config and make sure the plugin's name is listed in the spec.plugins sequence (add one if missing):

oc edit console.operator.openshift.io cluster
# ...
spec:
  plugins:
    - console-demo-plugin
# ...

Proxy service

In case the plugin needs to communicate with some in-cluster service, it can declare a service proxy in its ConsolePlugin resource using the spec.proxy array field. Each entry needs to specify an endpoint and alias of the proxy under the endpoint and alias fields. For the Service proxy type, the endpoint's type field will need to be set to Service and the service must include a name, namespace and port.

Console backend exposes following endpoint in order to proxy the communication between plugin and the service: /api/proxy/plugin/<plugin-name>/<proxy-alias>/<request-path>?<optional-query-parameters>

An example proxy request path from helm plugin with a helm-charts service to list ten helm releases: /api/proxy/plugin/helm/helm-charts/releases?limit=10

Proxied request will use service CA bundle by default. The service must use HTTPS. If the service uses a custom service CA, the caCertificate field must contain the certificate bundle. In case the service proxy request needs to contain the logged-in user's OpenShift access token, the authorization field needs to be set to UserToken. The user's OpenShift access token will be then passed in the HTTP Authorization request header, for example:

Authorization: Bearer sha256~kV46hPnEYhCWFnB85r5NrprAxggzgb6GOeLbgcKNsH0

# ...
spec:
  proxy:
  - alias: helm-charts
    authorization: UserToken
    caCertificate: '-----BEGIN CERTIFICATE-----\nMIID....'en
    endpoint:
      service:
        name: helm-charts
        namespace: helm
        port: 8443
      type: Service
# ...

If the service proxy request shouldn't contain the logged-in user's OpenShift access token, set the authorization field to None.

Local development

In case of local developement of the dynamic plugin, just set up your HTTP server locally and pass its endpoint address in form of a service proxy entry to the console server in form of JSON, using the --plugin-proxy flag.

Example:

 ./bin/bridge --plugin-proxy='{"services":[{"consoleAPIPath":"/api/proxy/namespace/serviceNamespace/service/serviceName:9991/","endpoint":"https://localhost:8080"}]}'

The service proxy entry besides service endpoint contain also consoleAPIPath, so the console server knows which path is should expose and proxy to service endpoint. Note that the service endpoint needs to contain scheme and consoleAPIPath needs to contain trailing slash in order for request to be proxied correctly.

Docker image

Following commands should be executed in Console repository root.

  1. Build the image:

    docker build -f Dockerfile.plugins.demo -t quay.io/$USER/console-demo-plugin .
  2. Run the image:

    docker run -it -p 9001:9001 quay.io/$USER/console-demo-plugin
  3. Push the image to image registry:

    docker push quay.io/$USER/console-demo-plugin

Update and apply oc-manifest.yaml to use a custom plugin image.

i18n

The demo plugin demonstrates how you can translate messages in a dynamic plugin with react-i18next. The i18n namespace must match the name of the ConsolePlugin resource with the plugin__ prefix to avoid naming conflicts. For example, the demo plugin uses the plugin__console-demo-plugin namespace. You can use the useTranslation hook with this namespace as follows:

conster Header: React.FC = () => {
  const { t } = useTranslation('plugin__console-demo-plugin');
  return <h1>{t('Hello, World!')}</h1>;
};

To indicate whether the ConsolePlugin contains localization resources, set the spec.i18n.loadType field based on needed behavior. Preload will load all plugin's localization resources from the i18n namespace named after the dynamic plugin during loading. In this case, plugin__console-demo-plugin. If set to Lazy, the plugin's localization resources won't be preloaded. They will be lazy-loaded instead.

spec:
  backend:
    service:
      basePath: /
      name: console-demo-plugin
      namespace: console-demo-plugin
      port: 9001
    type: Service
  displayName: OpenShift Console Demo Plugin
  i18n:
    loadType: Preload
  proxy:

The v1alpha1 apiVersion of ConsolePlugin supports console.openshift.io/use-i18n annotation, which indicates whether the ConsolePlugin contains localization resources. If the annotation is set to "true", the localization resources from the i18n namespace named after the dynamic plugin are preloaded. If the annotation is set to any other value or is missing on the ConsolePlugin resource, localization resources are not preloaded.

For labels in console-extensions.json, you can use the format %plugin__console-demo-plugin~My Label%. Console will replace the value with the message for the current language from the plugin__console-demo-plugin namespace. For example:

  {
    "type": "console.navigation/section",
    "properties": {
      "id": "admin-demo-section",
      "perspective": "admin",
      "name": "%plugin__console-demo-plugin~Demo Plugin%"
    }
  }

Note that you will need to include a comment in a TypeScript file like the following for i18next-parser to add the message from console-extensions.json to your message catalog.

// t('plugin__console-demo-plugin~Demo Plugin')

Running yarn i18n updates the JSON files in the locales folder of the dynamic plugin when adding or changing messages.