diff --git a/docs/development/plugins/functionality/extending-the-map.md b/docs/development/plugins/functionality/extending-the-map.md new file mode 100644 index 00000000000..2e81f1a1744 --- /dev/null +++ b/docs/development/plugins/functionality/extending-the-map.md @@ -0,0 +1,141 @@ +--- +title: Extending the Map +sidebar_label: Extending the Map +--- + +Map view displays cluster resource on a graph. Plugins can extend this graph by adding nodes and edges. + +## Nodes, edges and sources + +**Node** represents a Kubernetes resource. **Edges** connect different **nodes**, for example ReplicaSet connects to Pods it owns. + +
+ +![Screenshot of a Map with one ReplicaSet node connected to three Pods it owns](./images/map-rs-and-pods.png) + +
1 ReplicaSet and 3 Pods it owns
+
+ +To add your own nodes and edges you need to define a **Source** + +A graph **Source** represents a collection of Nodes and Edges along with name and icon. Source may contain other Sources. + +
+ +![Screenshot of a Source picker containing various Kubernetes resource sources](./images/source-picker-workloads.png) + +
Example: "Pods" is a source that contains Nodes for all the Pods in the cluster, "Workloads" is also a source containing other Sources.
+
+ +## Creating and registering a Source + +To define a Source create an object with the following structure: + +```tsx +const mySource = { + id: "my-source", // ID of the source should be unique + label: "My Source", // label will be displayed in source picker + // you can provide an icon + icon: ( + My Source logo + ), + /** + * useData is a hook that will be called to load nodes and edges for your source + * You can use hooks here that Headlamp provides to load Kubernetes resources + * this hook should return an object with nodes and edges or `null` if it's loading + * it's important that return object is not recreated every time, so useMemo is required + */ + useData() { + return useMemo(() => { + // This would come from kubernetes API but it's hardcoded here as an example + const myResource = { + kind: "MyResourceKind", + metadata: { + uid: "1234", + name: "my-test-resource", + namespace: "test-namespace", + creationTimestamp: "1234", + }, + }; + + const edges = []; // no edges in this source + const nodes = [ + { + id: "1234", // ID should be unique + type: "kubeObject", // 'kubeObject' type represnets a kubernetes resource + data: { + // resource field is required and should contain KubeObject + resource: new KubeObject(myResource), + }, + }, + ]; + + return { edges, nodes }; + }, []); + }, +}; +``` + +Then to register it call `registerMapSource` + +```tsx +registerMapSource(mySource); +``` + +You'll now see it in the Source picker and the Node on the Map: + +
+ +![Screenshot of a source picker](./images/source-picker.png) + +
"My Source" is listed on the bottom. Enabled by default.
+
+ +
+ +![Screenshot of a node with a default icon](./images/node-without-an-icon.png) + +
MyCustomResource Node displayed with default Icon
+
+ +## Node Icons + +To add an icon to the Node you need to call `registerKindIcon`. + +Note: This is different from the Source icon. One Source may contain multiple different kinds of objects. + +```tsx +registerKindIcon("MyCustomResource", { + // icon is a JSX element + icon: , +}); +``` + +
+ +![Screenshot of a node with a custom icon](./images/node-with-an-icon.png) + +
Node with a custom Icon
+
+ +## Details panel + +When selecting a Node Map will display a details panel for the selected object. +To add a details Panel for your Nodes call function `registerKindDetailsPage` + +```tsx +// You need to provide 'kind' of the resource and a React Component that will render details +// The props will contain name and a namespace of the Kubernetes Resource +// Details page usually loads the resource by name and namespace +registerKindDetailsPage("MyCustomResource", { + component: (props) => ( +
+ Details {props.name} {props.namespace} +
+ ), +}); +``` diff --git a/docs/development/plugins/functionality/images/map-rs-and-pods.png b/docs/development/plugins/functionality/images/map-rs-and-pods.png new file mode 100644 index 00000000000..b0a6acaa214 Binary files /dev/null and b/docs/development/plugins/functionality/images/map-rs-and-pods.png differ diff --git a/docs/development/plugins/functionality/images/node-with-an-icon.png b/docs/development/plugins/functionality/images/node-with-an-icon.png new file mode 100644 index 00000000000..89bfaae1bf0 Binary files /dev/null and b/docs/development/plugins/functionality/images/node-with-an-icon.png differ diff --git a/docs/development/plugins/functionality/images/node-without-an-icon.png b/docs/development/plugins/functionality/images/node-without-an-icon.png new file mode 100644 index 00000000000..e63e1cd7bfa Binary files /dev/null and b/docs/development/plugins/functionality/images/node-without-an-icon.png differ diff --git a/docs/development/plugins/functionality/images/source-picker-workloads.png b/docs/development/plugins/functionality/images/source-picker-workloads.png new file mode 100644 index 00000000000..f92de8a1071 Binary files /dev/null and b/docs/development/plugins/functionality/images/source-picker-workloads.png differ diff --git a/docs/development/plugins/functionality/images/source-picker.png b/docs/development/plugins/functionality/images/source-picker.png new file mode 100644 index 00000000000..c305bca8f71 Binary files /dev/null and b/docs/development/plugins/functionality/images/source-picker.png differ diff --git a/docs/development/plugins/functionality.md b/docs/development/plugins/functionality/index.md similarity index 92% rename from docs/development/plugins/functionality.md rename to docs/development/plugins/functionality/index.md index bae6407d088..4b88f992c94 100644 --- a/docs/development/plugins/functionality.md +++ b/docs/development/plugins/functionality/index.md @@ -59,7 +59,7 @@ what we have so far: Show a component in the app bar (in the top right) with [registerAppBarAction](../api/plugin/registry/functions/registerappbaraction). -![screenshot of the header showing two actions](./images/podcounter_screenshot.png) +![screenshot of the header showing two actions](../images/podcounter_screenshot.png) - Example plugin shows [How To Register an App Bar Action](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/pod-counter) - API reference for [registerAppBarAction](../api/plugin/registry/functions/registerappbaraction) @@ -69,7 +69,7 @@ Show a component in the app bar (in the top right) with Change the logo (at the top left) with [registerAppLogo](../api/plugin/registry/functions/registerapplogo). -![screenshot of the logo being changed](./images/change-logo.png) +![screenshot of the logo being changed](../images/change-logo.png) - Example plugin shows [How To Change The Logo](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/change-logo) - API reference for [registerAppLogo](../api/plugin/registry/functions/registerapplogo) @@ -79,7 +79,7 @@ Change the logo (at the top left) with Add menus when Headlamp is running as an app. [Headlamp.setAppMenu](../api/plugin/lib/classes/Headlamp#setappmenu) -![screenshot of the logo being changed](./images/app-menus.png) +![screenshot of the logo being changed](../images/app-menus.png) - Example plugin shows [How To Add App Menus](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/app-menus) - API reference for [Headlamp.setAppMenu](../api/plugin/lib/classes/Headlamp#setappmenu) @@ -89,7 +89,7 @@ Add menus when Headlamp is running as an app. Change the Cluster Chooser button (in the middle top of the Headlamp app bar) with [registerClusterChooser](../api/plugin/registry/functions/registerclusterchooser). -![screenshot of the cluster chooser button](./images/cluster-chooser.png) +![screenshot of the cluster chooser button](../images/cluster-chooser.png) - Example plugin shows [How To Register Cluster Chooser button](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/clusterchooser) - API reference for [registerClusterChooser](../api/plugin/registry/functions/registerclusterchooser) @@ -100,7 +100,7 @@ Show a component to the top right area of a detail view (in the area of the screenshot below that's highlighted as yellow) [registerDetailsViewHeaderAction](../api/plugin/registry/functions/registerdetailsviewheaderaction). -![screenshot of the header showing two actions](./images/header_actions_screenshot.png) +![screenshot of the header showing two actions](../images/header_actions_screenshot.png) - Example plugin shows [How To set a Details View Header Action](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/details-view) - API reference for [registerDetailsViewHeaderAction](../api/plugin/registry/functions/registerdetailsviewheaderaction) @@ -112,7 +112,7 @@ Change sections in cluster resources' details views with [registerDetailsViewSec Or simply append a component at the bottom of different details views with [registerDetailsViewSection](../api/plugin/registry/functions/registerdetailsviewsection). -![screenshot of the appended Details View Section](./images/details-view.jpeg) +![screenshot of the appended Details View Section](../images/details-view.jpeg) - Example plugin shows [How To set a Details View Section](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/details-view) - API reference for [registerDetailsViewSection](../api/plugin/registry/functions/registerdetailsviewsection) @@ -140,7 +140,7 @@ Add sidebar items (menu on the left) with [registerSidebarEntry](../api/plugin/registry/functions/registersidebarentry). Remove sidebar items with [registerSidebarEntryFilter](../api/plugin/registry/functions/registersidebarentryfilter). -![screenshot of the sidebar being changed](./images/sidebar.png) +![screenshot of the sidebar being changed](../images/sidebar.png) - Example plugin shows [How To add items to the sidebar](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/sidebar), and also how to remove sidebar items. - API reference for [registerSidebarEntry](../api/plugin/registry/functions/registersidebarentry) @@ -150,7 +150,7 @@ Remove sidebar items with [registerSidebarEntryFilter](../api/plugin/registry/fu Change what tables across Headlamp show with [registerResourceTableColumnsProcessor](../api/plugin/registry/functions/registersidebarentry). This allows you to remove, add, update, or shuffle table columns. -![screenshot of the pods list with a context menu added by a plugin](./images/table-context-menu.png) +![screenshot of the pods list with a context menu added by a plugin](../images/table-context-menu.png) - Example plugin shows [How to add a context menu to each row in the pods list table](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/tables). - API reference for [registerResourceTableColumnsProcessor](../api/plugin/registry/functions/registerresourcetablecolumnsprocessor) @@ -161,7 +161,7 @@ Headlamp has the concept of "Headlamp events". Those are fired when something re React to Headlamp events with [registerHeadlampEventCallback](../api/plugin/registry/functions/registerheadlampeventcallback). -![screenshot of a snackbar notification when an event occurred](./images/event-snackbar.png) +![screenshot of a snackbar notification when an event occurred](../images/event-snackbar.png) - Example plugin shows [How to show snackbars for Headlamp events](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/headlamp-events). - API reference for [registerHeadlampEventCallback](../api/plugin/registry/functions/registerheadlampeventcallback) @@ -172,4 +172,4 @@ The plugins can have user-configurable settings that can be used to change the b - Example plugin shows [How to create plugin settings and use them](https://github.com/headlamp-k8s/headlamp/tree/main/plugins/examples/change-logo) -![screenshot of the plugin settings](./images/plugin-settings.png) +![screenshot of the plugin settings](../images/plugin-settings.png)