Skip to content

OCPBUGS-54660: Expose topology components and utils via plugin SDK internal package #14777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: release-4.18
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dynamic-demo-plugin/console-extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@
"href": "/test-modal"
}
},
{
{
"type": "console.create-project-modal",
"properties": {
"component": { "$codeRef": "createProjectModal" }
Expand Down
3 changes: 2 additions & 1 deletion dynamic-demo-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"clean": "rm -rf dist",
"build": "yarn clean && NODE_ENV=production yarn ts-node node_modules/.bin/webpack",
"build-dev": "yarn clean && yarn ts-node node_modules/.bin/webpack",
"build-plugin-sdk": "yarn --cwd ../frontend build-plugin-sdk && rm -rf node_modules/@openshift-console && yarn install --check-files",
"build-plugin-sdk": "yarn --cwd ../frontend build-plugin-sdk && yarn install-plugin-sdk",
"install-plugin-sdk": "rm -rf node_modules/@openshift-console && yarn install --check-files",
"start-console": "./start-console.sh",
"http-server": "./http-server.sh dist",
"i18n": "i18next \"src/**/*.{js,jsx,ts,tsx}\" [-oc] -c i18next-parser.config.js",
Expand Down
1 change: 1 addition & 0 deletions dynamic-demo-plugin/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,7 @@ commander@^2.20.0:
commander@~7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==

[email protected]:
version "4.2.3"
Expand Down
93 changes: 62 additions & 31 deletions frontend/packages/console-dynamic-plugin-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,32 +64,37 @@ as a reference point for writing an OLM operator that ships with its own Console

## Distributable SDK package overview

| 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 code. |
| `@openshift-console/plugin-shared` | Provides reusable components and utility functions to build OCP dynamic plugins. Compatible with multiple versions of OpenShift Console. |
| 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.

## OpenShift Console Versions vs SDK Versions

Not all NPM packages are fully compatible with all versions of the Console. This table will help align
compatible versions of distributable SDK packages to versions of the OpenShift Console.

| Console Version | SDK Package | Last Package Version |
| ----------------- | ----------------------------------------------- | -------------------- |
| 4.17.x | `@openshift-console/dynamic-plugin-sdk` | Latest |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | Latest |
| 4.16.x | `@openshift-console/dynamic-plugin-sdk` | 1.4.0 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 1.1.1 |
| 4.15.x | `@openshift-console/dynamic-plugin-sdk` | 1.0.0 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 1.0.2 |
| 4.14.x | `@openshift-console/dynamic-plugin-sdk` | 0.0.21 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 0.0.11 |
| 4.13.x | `@openshift-console/dynamic-plugin-sdk` | 0.0.19 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 0.0.9 |
| 4.12.x | `@openshift-console/dynamic-plugin-sdk` | 0.0.18 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 0.0.9 |
| Console Version | SDK Package | Last Package Version |
| --------------- | ----------------------------------------------- | -------------------- |
| 4.18.x | `@openshift-console/dynamic-plugin-sdk` | 1.8.0 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 1.3.0 |
| 4.17.x | `@openshift-console/dynamic-plugin-sdk` | 1.6.0 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 1.2.0 |
| 4.16.x | `@openshift-console/dynamic-plugin-sdk` | 1.4.0 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 1.1.1 |
| 4.15.x | `@openshift-console/dynamic-plugin-sdk` | 1.0.0 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 1.0.2 |
| 4.14.x | `@openshift-console/dynamic-plugin-sdk` | 0.0.21 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 0.0.11 |
| 4.13.x | `@openshift-console/dynamic-plugin-sdk` | 0.0.19 |
| | `@openshift-console/dynamic-plugin-sdk-webpack` | 0.0.9 |
| 4.12.x | `@openshift-console/dynamic-plugin-sdk` | 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](https://access.redhat.com/support/policy/updates/openshift).
Expand Down Expand Up @@ -159,13 +164,12 @@ This section documents notable changes in the Console provided shared modules ac
- All Console provided React Router v5 shared modules are deprecated and will be removed in the future.
Plugins should upgrade to React Router v6 via `react-router-dom-v5-compat` module.

### PatternFly dynamic modules
### PatternFly 5+ dynamic modules

Newer versions of `@openshift-console/dynamic-plugin-sdk-webpack` package (1.0.0 and higher) include
support for automatic detection and sharing of individual PatternFly 5.x dynamic modules.
Newer versions of `@openshift-console/dynamic-plugin-sdk-webpack` package include support for automatic
detection and sharing of individual PatternFly 5+ dynamic modules.

Plugins using PatternFly 5.x dependencies should generally avoid non-index imports for any PatternFly
packages, for example:
Plugins using PatternFly 5.x and newer should avoid non-index imports, for example:

```ts
// Do _not_ do this:
Expand All @@ -182,20 +186,47 @@ Console application uses [Content Security Policy](https://developer.mozilla.org
includes the document origin `'self'` and Console webpack dev server when running off-cluster.

All dynamic plugin assets _should_ be loaded using `/api/plugins/<plugin-name>` Bridge endpoint which
matches the `'self'` CSP source of Console application.
matches the `'self'` CSP source for all Console assets served via Bridge.

See `cspSources` and `cspDirectives` in
[`pkg/server/server.go`](https://github.com/openshift/console/blob/master/pkg/server/server.go)
Refer to `BuildCSPDirectives` function in
[`pkg/utils/utils.go`](https://github.com/openshift/console/blob/release-4.18/pkg/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.

### Changes in Console CSP

This section documents notable changes in the Console Content Security Policy.
This section documents notable changes in the Console Content Security Policy implementation.

#### Console 4.18.x

Console CSP is deployed in report-only mode. CSP violations will be logged in the browser console
but the associated CSP directives will not be enforced.
Console CSP feature is disabled by default. To test your plugins with CSP, enable the
`ConsolePluginContentSecurityPolicy` feature gate on a test cluster. This feature gate
should **not** be enabled on production clusters. Enabling this feature gate allows you
to set `spec.contentSecurityPolicy` in your `ConsolePlugin` resource to extend existing
CSP directives, for example:

```yaml
apiVersion: console.openshift.io/v1
kind: ConsolePlugin
metadata:
name: cron-tab
spec:
displayName: 'Cron Tab'
contentSecurityPolicy:
- directive: 'ScriptSrc'
values:
- 'https://example1.com/'
- 'https://example2.com/'
```

When enabled, Console CSP operates in report-only mode; CSP violations will be logged in
the browser and CSP violation data will be reported through telemetry service in production
deployments.

In a future release, Console will begin enforcing CSP. Consider testing and preparing your
plugins now to avoid CSP related issues in future.

## Plugin metadata

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ const rootPackage = readPkg.sync({ cwd: resolvePath('../..'), normalize: false }
const missingDepNames = new Set<string>();
const missingDepCallback = (name: string) => missingDepNames.add(name);

const outPackages = [
getCorePackage(sdkPackage, rootPackage, missingDepCallback),
getInternalPackage(sdkPackage, rootPackage, missingDepCallback),
getWebpackPackage(sdkPackage, rootPackage, missingDepCallback),
];
const outPackages = [getCorePackage, getInternalPackage, getWebpackPackage].map((getPkg) =>
getPkg(sdkPackage, rootPackage, missingDepCallback),
);

if (missingDepNames.size > 0) {
console.error(`Failed to parse package dependencies: ${Array.from(missingDepNames).join(', ')}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export const getCorePackage: GetPackageDefinition = (
manifest: {
name: '@openshift-console/dynamic-plugin-sdk',
version: sdkPackage.version,
description: 'Provides core APIs, types and utilities used by dynamic plugins at runtime.',
main: 'lib/lib-core.js',
...commonManifestFields,
dependencies: {
Expand Down Expand Up @@ -133,6 +134,7 @@ export const getInternalPackage: GetPackageDefinition = (
manifest: {
name: '@openshift-console/dynamic-plugin-sdk-internal',
version: sdkPackage.version,
description: 'Internal package exposing additional Console code.',
main: 'lib/lib-internal.js',
...commonManifestFields,
dependencies: {
Expand All @@ -154,6 +156,7 @@ export const getWebpackPackage: GetPackageDefinition = (
manifest: {
name: '@openshift-console/dynamic-plugin-sdk-webpack',
version: sdkPackage.version,
description: 'Provides webpack ConsoleRemotePlugin used to build all dynamic plugin assets.',
main: 'lib/lib-webpack.js',
...commonManifestFields,
dependencies: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export type Selector = {
matchExpressions?: MatchExpression[];
};

type K8sVerb =
export type K8sVerb =
| 'create'
| 'get'
| 'list'
Expand Down Expand Up @@ -165,6 +165,12 @@ export type Alert = PrometheusAlert & {
silencedBy?: Silence[];
};

export type Alerts = {
data: Alert[];
loaded: boolean;
loadError?: string | Error;
};

export type PrometheusRule = {
alerts: PrometheusAlert[];
annotations: PrometheusLabels;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable */
import * as React from 'react';
import {
ActivityItemProps,
ActivityBodyProps,
Expand All @@ -20,7 +21,9 @@ import {
UseURLPoll,
UseLastNamespace,
} from './internal-types';
import { UseUserSettings } from '../extensions';
import { UseUserSettings } from '../extensions/console-types';

export * from './internal-topology-api';

export const ActivityItem: React.FC<ActivityItemProps> = require('@console/shared/src/components/dashboard/activity-card/ActivityItem')
.default;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* eslint-disable */
import * as React from 'react';
import {
CpuCellComponentProps,
MemoryCellComponentProps,
TopologyListViewNodeProps,
UseOverviewMetrics,
WithEditReviewAccess,
GetPodMetricStats,
GetTopologyResourceObject,
GetResource,
GetTopologyEdgeItems,
GetTopologyGroupItems,
GetTopologyNodeItem,
MergeGroup,
GetModifyApplicationAction,
BaseDataModelGetter,
GetWorkloadResources,
ContextMenuActions,
CreateConnectorProps,
} from '../extensions/topology-types';

export const CpuCellComponent: React.FC<CpuCellComponentProps> = require('@console/topology/src/components/list-view/cells/CpuCell')
.CpuCellComponent;

export const MemoryCellComponent: React.FC<MemoryCellComponentProps> = require('@console/topology/src/components/list-view/cells/MemoryCell')
.MemoryCellComponent;

export const TopologyListViewNode: React.FC<TopologyListViewNodeProps> = require('@console/topology/src/components/list-view/TopologyListViewNode')
.default;

export const useOverviewMetrics: UseOverviewMetrics = require('@console/topology/src/utils/useOverviewMetrics')
.useOverviewMetrics;

export const withEditReviewAccess: WithEditReviewAccess = require('@console/topology/src/utils/withEditReviewAccess')
.withEditReviewAccess;

export const getPodMetricStats: GetPodMetricStats = require('@console/topology/src/utils/metricStats')
.getPodMetricStats;

export const getTopologyResourceObject: GetTopologyResourceObject = require('@console/topology/src/utils/topology-utils')
.getTopologyResourceObject;

export const getResource: GetResource = require('@console/topology/src/utils/topology-utils')
.getResource;

export const getTopologyEdgeItems: GetTopologyEdgeItems = require('@console/topology/src/data-transforms/transform-utils')
.getTopologyEdgeItems;

export const getTopologyGroupItems: GetTopologyGroupItems = require('@console/topology/src/data-transforms/transform-utils')
.getTopologyGroupItems;

export const getTopologyNodeItem: GetTopologyNodeItem = require('@console/topology/src/data-transforms/transform-utils')
.getTopologyNodeItem;

export const mergeGroup: MergeGroup = require('@console/topology/src/data-transforms/transform-utils')
.mergeGroup;

export const getModifyApplicationAction: GetModifyApplicationAction = require('@console/topology/src/actions/modify-application')
.getModifyApplicationAction;

export const baseDataModelGetter: BaseDataModelGetter = require('@console/topology/src/data-transforms/data-transformer')
.baseDataModelGetter;

export const getWorkloadResources: GetWorkloadResources = require('@console/topology/src/data-transforms/transform-utils')
.getWorkloadResources;

export const contextMenuActions: ContextMenuActions = require('@console/topology/src/actions/contextMenuActions')
.contextMenuActions;

export const CreateConnector: CreateConnectorProps = require('@console/topology/src/components/graph-view')
.CreateConnector;

export const createConnectorCallback = require('@console/topology/src/components/graph-view')
.createConnectorCallback;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react';
import * as _ from 'lodash';
import { K8sVerb } from '../../../api/common-types';
import {
AccessReviewResourceAttributes,
K8sVerb,
SelfSubjectAccessReviewKind,
} from '../../../extensions/console-types';
import { ProjectModel, SelfSubjectAccessReviewModel } from '../../../models';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Store, AnyAction } from 'redux';
import { ActionType as Action } from 'typesafe-actions';
import { K8sVerb } from '../../../extensions/console-types';
import { K8sVerb } from '../../../api/common-types';

export type InitApiDiscovery = (store: Store<any, Action<AnyAction>>) => void;

Expand Down
Loading