mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
1550 lines
113 KiB
HTML
1550 lines
113 KiB
HTML
|
|
<!doctype html>
|
|
<html lang="en" class="no-js">
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
|
|
<meta name="description" content="Documentation for Lens Extension Development and API.">
|
|
|
|
|
|
<link rel="canonical" href="https://api-docs.k8slens.dev/v4.0.8/extensions/guides/renderer-extension/">
|
|
|
|
|
|
<meta name="author" content="Mirantis, Inc.">
|
|
|
|
<link rel="shortcut icon" href="../../../img/favicon.ico">
|
|
<meta name="generator" content="mkdocs-1.2, mkdocs-material-6.1.0+insiders-1.7.0">
|
|
|
|
|
|
|
|
<title>Renderer Extension - Lens Extension Development</title>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../../assets/stylesheets/main.406af9ae.min.css">
|
|
|
|
|
|
<link rel="stylesheet" href="../../../assets/stylesheets/palette.ec60dfa4.min.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback">
|
|
<style>body,input{font-family:"Roboto",-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono",SFMono-Regular,Consolas,Menlo,monospace}</style>
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../../stylesheets/extra.css">
|
|
|
|
|
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-90E1JB4HW4"></script>
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
gtag('config', 'G-90E1JB4HW4');
|
|
</script>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="" data-md-color-accent="">
|
|
|
|
|
|
<script>var palette=JSON.parse(localStorage.getItem("__palette")||"{}");if(void 0!==palette.color)for(var key in palette.color)document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
|
|
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
|
<label class="md-overlay" for="__drawer"></label>
|
|
<div data-md-component="skip">
|
|
|
|
|
|
<a href="#renderer-extension" class="md-skip">
|
|
Skip to content
|
|
</a>
|
|
|
|
</div>
|
|
<div data-md-component="announce">
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<header class="md-header" data-md-component="header">
|
|
<nav class="md-header-nav md-grid" aria-label="Header">
|
|
<a href="https://api-docs.k8slens.dev/v4.0.8" title="Lens Extension Development" class="md-header-nav__button md-logo" aria-label="Lens Extension Development">
|
|
|
|
<img src="../../../img/lens-logo-icon.svg" alt="logo">
|
|
|
|
</a>
|
|
<label class="md-header-nav__button md-icon" for="__drawer">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg>
|
|
</label>
|
|
<div class="md-header-nav__title" data-md-component="header-title">
|
|
<div class="md-header-nav__ellipsis">
|
|
<div class="md-header-nav__topic">
|
|
<span class="md-ellipsis">
|
|
Lens Extension Development
|
|
</span>
|
|
</div>
|
|
<div class="md-header-nav__topic">
|
|
<span class="md-ellipsis">
|
|
|
|
Renderer Extension
|
|
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="md-header-nav__options">
|
|
|
|
|
|
|
|
|
|
|
|
<button class="md-header-nav__button md-icon" title="Switch to dark mode" aria-label="Switch to dark mode" data-md-option="palette" data-md-color-scheme="slate" data-md-color-primary="" data-md-color-accent="" data-md-state="hidden">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 10a2 2 0 012 2 2 2 0 01-2 2 2 2 0 01-2-2 2 2 0 012-2m10-3a5 5 0 015 5 5 5 0 01-5 5H7a5 5 0 01-5-5 5 5 0 015-5h10M7 9a3 3 0 00-3 3 3 3 0 003 3h10a3 3 0 003-3 3 3 0 00-3-3H7z"/></svg>
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<button class="md-header-nav__button md-icon" title="Switch to light mode" aria-label="Switch to light mode" data-md-option="palette" data-md-color-scheme="default" data-md-color-primary="" data-md-color-accent="" data-md-state="hidden">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 7H7a5 5 0 00-5 5 5 5 0 005 5h10a5 5 0 005-5 5 5 0 00-5-5m0 8a3 3 0 01-3-3 3 3 0 013-3 3 3 0 013 3 3 3 0 01-3 3z"/></svg>
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
<label class="md-header-nav__button md-icon" for="__search">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
|
|
</label>
|
|
|
|
<div class="md-search" data-md-component="search" role="dialog">
|
|
<label class="md-search__overlay" for="__search"></label>
|
|
<div class="md-search__inner" role="search">
|
|
<form class="md-search__form" name="search">
|
|
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" data-md-state="active">
|
|
<label class="md-search__icon md-icon" for="__search">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
|
|
</label>
|
|
<button type="reset" class="md-search__icon md-icon" aria-label="Clear" data-md-component="search-reset" tabindex="-1">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
|
|
</button>
|
|
<div class="md-search__suggest" data-md-component="search-suggest"></div>
|
|
</form>
|
|
<div class="md-search__output">
|
|
<div class="md-search__scrollwrap" data-md-scrollfix>
|
|
<div class="md-search-result" data-md-component="search-result">
|
|
<div class="md-search-result__meta">
|
|
Initializing search
|
|
</div>
|
|
<ol class="md-search-result__list"></ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="md-header-nav__source">
|
|
|
|
<a href="https://github.com/lensapp/lens" title="Go to repository" class="md-source">
|
|
<div class="md-source__icon md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05L244 40.45a28.87 28.87 0 00-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 01-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-40.81z"/></svg>
|
|
</div>
|
|
<div class="md-source__repository">
|
|
GitHub
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
</nav>
|
|
</header>
|
|
|
|
<div class="md-container" data-md-component="container">
|
|
|
|
|
|
|
|
|
|
<main class="md-main" data-md-component="main">
|
|
<div class="md-main__inner md-grid">
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
|
|
|
|
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
|
<label class="md-nav__title" for="__drawer">
|
|
<a href="https://api-docs.k8slens.dev/v4.0.8" title="Lens Extension Development" class="md-nav__button md-logo" aria-label="Lens Extension Development">
|
|
|
|
<img src="../../../img/lens-logo-icon.svg" alt="logo">
|
|
|
|
</a>
|
|
Lens Extension Development
|
|
</label>
|
|
|
|
<div class="md-nav__source">
|
|
|
|
<a href="https://github.com/lensapp/lens" title="Go to repository" class="md-source">
|
|
<div class="md-source__icon md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05L244 40.45a28.87 28.87 0 00-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 01-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-40.81z"/></svg>
|
|
</div>
|
|
<div class="md-source__repository">
|
|
GitHub
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../.." class="md-nav__link">
|
|
Overview
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-2" type="checkbox" id="nav-2">
|
|
|
|
<label class="md-nav__link" for="nav-2">
|
|
Getting Started
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Getting Started" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-2">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Getting Started
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../get-started/overview/" class="md-nav__link">
|
|
Overview
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../get-started/your-first-extension/" class="md-nav__link">
|
|
Your First Extension
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../get-started/anatomy/" class="md-nav__link">
|
|
Extension Anatomy
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../get-started/wrapping-up/" class="md-nav__link">
|
|
Wrapping Up
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-3" type="checkbox" id="nav-3">
|
|
|
|
<label class="md-nav__link" for="nav-3">
|
|
Extension Capabilities
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Extension Capabilities" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-3">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Extension Capabilities
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../capabilities/common-capabilities/" class="md-nav__link">
|
|
Common Capabilities
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../capabilities/styling/" class="md-nav__link">
|
|
Styling
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-4" type="checkbox" id="nav-4" checked>
|
|
|
|
<label class="md-nav__link" for="nav-4">
|
|
Extension Guides
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Extension Guides" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-4">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Extension Guides
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../" class="md-nav__link">
|
|
Overview
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../generator/" class="md-nav__link">
|
|
Generator
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../main-extension/" class="md-nav__link">
|
|
Main Extension
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active">
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc">
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__link md-nav__link--active" for="__toc">
|
|
Renderer Extension
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<a href="./" class="md-nav__link md-nav__link--active">
|
|
Renderer Extension
|
|
</a>
|
|
|
|
|
|
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__title" for="__toc">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Table of contents
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#lensrendererextension-class" class="md-nav__link">
|
|
LensRendererExtension Class
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="LensRendererExtension Class">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#clusterpages" class="md-nav__link">
|
|
clusterPages
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#clusterpagemenus" class="md-nav__link">
|
|
clusterPageMenus
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#globalpages" class="md-nav__link">
|
|
globalPages
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#globalpagemenus" class="md-nav__link">
|
|
globalPageMenus
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#clusterfeatures" class="md-nav__link">
|
|
clusterFeatures
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#apppreferences" class="md-nav__link">
|
|
appPreferences
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#statusbaritems" class="md-nav__link">
|
|
statusBarItems
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#kubeobjectmenuitems" class="md-nav__link">
|
|
kubeObjectMenuItems
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#kubeobjectdetailitems" class="md-nav__link">
|
|
kubeObjectDetailItems
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../stores/" class="md-nav__link">
|
|
Stores
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../working-with-mobx/" class="md-nav__link">
|
|
Working with MobX
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="nav-5" type="checkbox" id="nav-5">
|
|
|
|
<label class="md-nav__link" for="nav-5">
|
|
Testing and Publishing
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Testing and Publishing" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-5">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Testing and Publishing
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../testing-and-publishing/testing/" class="md-nav__link">
|
|
Testing Extensions
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../testing-and-publishing/publishing/" class="md-nav__link">
|
|
Publishing Extensions
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../api/" class="md-nav__link">
|
|
API Reference
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
|
|
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__title" for="__toc">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Table of contents
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#lensrendererextension-class" class="md-nav__link">
|
|
LensRendererExtension Class
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="LensRendererExtension Class">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#clusterpages" class="md-nav__link">
|
|
clusterPages
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#clusterpagemenus" class="md-nav__link">
|
|
clusterPageMenus
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#globalpages" class="md-nav__link">
|
|
globalPages
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#globalpagemenus" class="md-nav__link">
|
|
globalPageMenus
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#clusterfeatures" class="md-nav__link">
|
|
clusterFeatures
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#apppreferences" class="md-nav__link">
|
|
appPreferences
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#statusbaritems" class="md-nav__link">
|
|
statusBarItems
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#kubeobjectmenuitems" class="md-nav__link">
|
|
kubeObjectMenuItems
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#kubeobjectdetailitems" class="md-nav__link">
|
|
kubeObjectDetailItems
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="md-content">
|
|
<article class="md-content__inner md-typeset">
|
|
|
|
|
|
|
|
<h1 id="renderer-extension">Renderer Extension<a class="headerlink" href="#renderer-extension" title="Permanent link">#</a></h1>
|
|
<p>The renderer extension api is the interface to Lens's renderer process (Lens runs in main and renderer processes).
|
|
It allows you to access, configure, and customize Lens data, add custom Lens UI elements, and generally run custom code in Lens's renderer process.
|
|
The custom Lens UI elements that can be added include global pages, cluster pages, cluster page menus, cluster features, app preferences, status bar items, KubeObject menu items, and KubeObject details items.
|
|
These UI elements are based on React components.</p>
|
|
<h2 id="lensrendererextension-class"><code>LensRendererExtension</code> Class<a class="headerlink" href="#lensrendererextension-class" title="Permanent link">#</a></h2>
|
|
<p>To create a renderer extension simply extend the <code>LensRendererExtension</code> class:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">ExampleExtensionMain</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">onActivate</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'custom renderer process extension code started'</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="nx">onDeactivate</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'custom renderer process extension de-activated'</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>There are two methods that you can implement to facilitate running your custom code.
|
|
<code>onActivate()</code> is called when your extension has been successfully enabled.
|
|
By implementing <code>onActivate()</code> you can initiate your custom code.
|
|
<code>onDeactivate()</code> is called when the extension is disabled (typically from the <a href="">Lens Extensions Page</a>) and when implemented gives you a chance to clean up after your extension, if necessary.
|
|
The example above simply logs messages when the extension is enabled and disabled.</p>
|
|
<h3 id="clusterpages"><code>clusterPages</code><a class="headerlink" href="#clusterpages" title="Permanent link">#</a></h3>
|
|
<p>Cluster pages appear as part of the cluster dashboard.
|
|
They are accessible from the side bar, and are shown in the menu list after <em>Custom Resources</em>.
|
|
It is conventional to use a cluster page to show information or provide functionality pertaining to the active cluster, along with custom data and functionality your extension may have.
|
|
However, it is not limited to the active cluster.
|
|
Also, your extension can gain access to the Kubernetes resources in the active cluster in a straightforward manner using the <a href="../stores#clusterstore"><code>clusterStore</code></a>.</p>
|
|
<p>The following example adds a cluster page definition to a <code>LensRendererExtension</code> subclass:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">ExampleIcon</span><span class="p">,</span> <span class="nx">ExamplePage</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./page"</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">ExampleExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">clusterPages</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">id</span><span class="o">:</span> <span class="s2">"hello"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Page</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">ExamplePage</span> <span class="nx">extension</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">}</span><span class="o">/></span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Cluster pages are objects matching the <code>PageRegistration</code> interface.
|
|
The <code>id</code> field identifies the page, and at its simplest is just a string identifier, as shown in the example above.
|
|
The 'id' field can also convey route path details, such as variable parameters provided to a page (<a href="">See example below</a>).
|
|
The <code>components</code> field matches the <code>PageComponents</code> interface for wich there is one field, <code>Page</code>.
|
|
<code>Page</code> is of type <code>React.ComponentType<any></code>, which gives you great flexibility in defining the appearance and behaviour of your page.
|
|
For the example above <code>ExamplePage</code> can be defined in <code>page.tsx</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">ExamplePage</span> <span class="k">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="o"><</span><span class="p">{</span> <span class="nx">extension</span>: <span class="kt">LensRendererExtension</span> <span class="p">}</span><span class="o">></span> <span class="p">{</span>
|
|
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">p</span><span class="o">></span><span class="nx">Hello</span> <span class="nx">world</span><span class="o">!<</span><span class="err">/p></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Note that the <code>ExamplePage</code> class defines a property named <code>extension</code>.
|
|
This allows the <code>ExampleExtension</code> object to be passed in React-style in the cluster page definition, so that <code>ExamplePage</code> can access any <code>ExampleExtension</code> subclass data.</p>
|
|
<h3 id="clusterpagemenus"><code>clusterPageMenus</code><a class="headerlink" href="#clusterpagemenus" title="Permanent link">#</a></h3>
|
|
<p>The above example code shows how to create a cluster page but not how to make it available to the Lens user.
|
|
Cluster pages are typically made available through a menu item in the cluster dashboard sidebar.
|
|
Expanding on the above example a cluster page menu is added to the <code>ExampleExtension</code> definition:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">ExampleIcon</span><span class="p">,</span> <span class="nx">ExamplePage</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./page"</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">ExampleExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">clusterPages</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">id</span><span class="o">:</span> <span class="s2">"hello"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Page</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">ExamplePage</span> <span class="nx">extension</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">}</span><span class="o">/></span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
|
|
<span class="nx">clusterPageMenus</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">target</span><span class="o">:</span> <span class="p">{</span> <span class="nx">pageId</span><span class="o">:</span> <span class="s2">"hello"</span> <span class="p">},</span>
|
|
<span class="nx">title</span><span class="o">:</span> <span class="s2">"Hello World"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Icon</span>: <span class="kt">ExampleIcon</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">},</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Cluster page menus are objects matching the <code>ClusterPageMenuRegistration</code> interface.
|
|
They define the appearance of the cluster page menu item in the cluster dashboard sidebar and the behaviour when the cluster page menu item is activated (typically by a mouse click).
|
|
The example above uses the <code>target</code> field to set the behaviour as a link to the cluster page with <code>id</code> of <code>"hello"</code>.
|
|
This is done by setting <code>target</code>'s <code>pageId</code> field to <code>"hello"</code>.
|
|
The cluster page menu item's appearance is defined by setting the <code>title</code> field to the text that is to be displayed in the cluster dashboard sidebar.
|
|
The <code>components</code> field is used to set an icon that appears to the left of the <code>title</code> text in the sidebar.
|
|
Thus when the <code>"Hello World"</code> menu item is activated the cluster dashboard will show the contents of <code>ExamplePage</code>.
|
|
This example requires the definition of another React-based component, <code>ExampleIcon</code>, which has been added to <code>page.tsx</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span><span class="p">,</span> <span class="nx">Component</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="kd">function</span> <span class="nx">ExampleIcon</span><span class="p">(</span><span class="nx">props</span>: <span class="kt">Component.IconProps</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">Icon</span> <span class="p">{...</span><span class="nx">props</span><span class="p">}</span> <span class="nx">material</span><span class="o">=</span><span class="s2">"pages"</span> <span class="nx">tooltip</span><span class="o">=</span><span class="p">{</span><span class="s2">"Hi!"</span><span class="p">}</span><span class="o">/></span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">ExamplePage</span> <span class="k">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="o"><</span><span class="p">{</span> <span class="nx">extension</span>: <span class="kt">LensRendererExtension</span> <span class="p">}</span><span class="o">></span> <span class="p">{</span>
|
|
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">p</span><span class="o">></span><span class="nx">Hello</span> <span class="nx">world</span><span class="o">!<</span><span class="err">/p></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p><code>ExampleIcon</code> introduces one of Lens's built-in components available to extension developers, the <code>Component.Icon</code>.
|
|
Built in are the <a href="https://material.io">Material Design</a> <a href="https://material.io/resources/icons/">icons</a>.
|
|
One can be selected by name via the <code>material</code> field.
|
|
<code>ExampleIcon</code> also sets a tooltip, shown when the Lens user hovers over the icon with a mouse, by setting the <code>tooltip</code> field.</p>
|
|
<p>A cluster page menu can also be used to define a foldout submenu in the cluster dashboard sidebar.
|
|
This enables the grouping of cluster pages.
|
|
The following example shows how to specify a submenu having two menu items:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">ExampleIcon</span><span class="p">,</span> <span class="nx">ExamplePage</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./page"</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">ExampleExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">clusterPages</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">id</span><span class="o">:</span> <span class="s2">"hello"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Page</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">ExamplePage</span> <span class="nx">extension</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">}</span><span class="o">/></span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">id</span><span class="o">:</span> <span class="s2">"bonjour"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Page</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">ExemplePage</span> <span class="nx">extension</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">}</span><span class="o">/></span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
|
|
<span class="nx">clusterPageMenus</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">id</span><span class="o">:</span> <span class="s2">"example"</span><span class="p">,</span>
|
|
<span class="nx">title</span><span class="o">:</span> <span class="s2">"Greetings"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Icon</span>: <span class="kt">ExampleIcon</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">parentId</span><span class="o">:</span> <span class="s2">"example"</span><span class="p">,</span>
|
|
<span class="nx">target</span><span class="o">:</span> <span class="p">{</span> <span class="nx">pageId</span><span class="o">:</span> <span class="s2">"hello"</span> <span class="p">},</span>
|
|
<span class="nx">title</span><span class="o">:</span> <span class="s2">"Hello World"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Icon</span>: <span class="kt">ExampleIcon</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">parentId</span><span class="o">:</span> <span class="s2">"example"</span><span class="p">,</span>
|
|
<span class="nx">target</span><span class="o">:</span> <span class="p">{</span> <span class="nx">pageId</span><span class="o">:</span> <span class="s2">"bonjour"</span> <span class="p">},</span>
|
|
<span class="nx">title</span><span class="o">:</span> <span class="s2">"Bonjour le monde"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Icon</span>: <span class="kt">ExempleIcon</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>The above defines two cluster pages and three cluster page menu objects.
|
|
The cluster page definitons are straightforward.
|
|
The first cluster page menu object defines the parent of a foldout submenu.
|
|
Setting the <code>id</code> field in a cluster page menu definition implies that it is defining a foldout submenu.
|
|
Also note that the <code>target</code> field is not specified (it is ignored if the <code>id</code> field is specified).
|
|
This cluster page menu object specifies the <code>title</code> and <code>components</code> fields, which are used in displaying the menu item in the cluster dashboard sidebar.
|
|
Initially the submenu is hidden.
|
|
Activating this menu item toggles on and off the appearance of the submenu below it.
|
|
The remaining two cluster page menu objects define the contents of the submenu.
|
|
A cluster page menu object is defined to be a submenu item by setting the <code>parentId</code> field to the id of the parent of a foldout submenu, <code>"example"</code> in this case</p>
|
|
<h3 id="globalpages"><code>globalPages</code><a class="headerlink" href="#globalpages" title="Permanent link">#</a></h3>
|
|
<p>Global pages appear independently of the cluster dashboard and they fill the Lens UI space.
|
|
A global page is typically triggered from the cluster menu using a <a href="#globalpagemenus">global page menu</a>.
|
|
They can also be triggered by a <a href="../main-extension#appmenus">custom app menu selection</a> from a Main Extension or a <a href="#statusbaritems">custom status bar item</a>.
|
|
Global pages can appear even when there is no active cluster, unlike cluster pages.
|
|
It is conventional to use a global page to show information and provide functionality relevant across clusters, along with custom data and functionality that your extension may have.</p>
|
|
<p>The following example defines a <code>LensRendererExtension</code> subclass with a single global page definition:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s1">'@k8slens/extensions'</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">HelpPage</span> <span class="p">}</span> <span class="k">from</span> <span class="s1">'./page'</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s1">'react'</span><span class="p">;</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">HelpExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">globalPages</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">id</span><span class="o">:</span> <span class="s2">"help"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Page</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">HelpPage</span> <span class="nx">extension</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">}</span><span class="o">/></span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Global pages are objects matching the <code>PageRegistration</code> interface.
|
|
The <code>id</code> field identifies the page, and at its simplest is just a string identifier, as shown in the example above.
|
|
The 'id' field can also convey route path details, such as variable parameters provided to a page (<a href="">See example below</a>).
|
|
The <code>components</code> field matches the <code>PageComponents</code> interface for which there is one field, <code>Page</code>.
|
|
<code>Page</code> is of type <code>React.ComponentType<any></code>, which gives you great flexibility in defining the appearance and behaviour of your page.
|
|
For the example above <code>HelpPage</code> can be defined in <code>page.tsx</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">HelpPage</span> <span class="k">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="o"><</span><span class="p">{</span> <span class="nx">extension</span>: <span class="kt">LensRendererExtension</span> <span class="p">}</span><span class="o">></span> <span class="p">{</span>
|
|
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">p</span><span class="o">></span><span class="nx">Help</span> <span class="nx">yourself</span><span class="o"><</span><span class="err">/p></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Note that the <code>HelpPage</code> class defines a property named <code>extension</code>.
|
|
This allows the <code>HelpExtension</code> object to be passed in React-style in the global page definition, so that <code>HelpPage</code> can access any <code>HelpExtension</code> subclass data.</p>
|
|
<p>This example code shows how to create a global page but not how to make it available to the Lens user.
|
|
Global pages are typically made available through a number of ways.
|
|
Menu items can be added to the Lens app menu system and set to open a global page when activated (See <a href="../main-extension#appmenus"><code>appMenus</code> in the Main Extension guide</a>).
|
|
Interactive elements can be placed on the status bar (the blue strip along the bottom of the Lens UI) and can be configured to link to a global page when activated (See <a href="#statusbaritems"><code>statusBarItems</code></a>).
|
|
As well, global pages can be made accessible from the cluster menu, which is the vertical strip along the left side of the Lens UI showing the available cluster icons, and the Add Cluster icon.
|
|
Global page menu icons that are defined using <a href="#globalpagemenus"><code>globalPageMenus</code></a> appear below the Add Cluster icon.</p>
|
|
<h3 id="globalpagemenus"><code>globalPageMenus</code><a class="headerlink" href="#globalpagemenus" title="Permanent link">#</a></h3>
|
|
<p>Global page menus connect a global page to the cluster menu, which is the vertical strip along the left side of the Lens UI showing the available cluster icons, and the Add Cluster icon.
|
|
Expanding on the example from <a href="#globalPages"><code>globalPages</code></a> a global page menu is added to the <code>HelpExtension</code> definition:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">HelpIcon</span><span class="p">,</span> <span class="nx">HelpPage</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./page"</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">HelpExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">globalPages</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">id</span><span class="o">:</span> <span class="s2">"help"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Page</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">HelpPage</span> <span class="nx">extension</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">}</span><span class="o">/></span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
|
|
<span class="nx">globalPageMenus</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">target</span><span class="o">:</span> <span class="p">{</span> <span class="nx">pageId</span><span class="o">:</span> <span class="s2">"help"</span> <span class="p">},</span>
|
|
<span class="nx">title</span><span class="o">:</span> <span class="s2">"Help"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Icon</span>: <span class="kt">HelpIcon</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">},</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Global page menus are objects matching the <code>PageMenuRegistration</code> interface.
|
|
They define the appearance of the global page menu item in the cluster menu and the behaviour when the global page menu item is activated (typically by a mouse click).
|
|
The example above uses the <code>target</code> field to set the behaviour as a link to the global page with <code>id</code> of <code>"help"</code>.
|
|
This is done by setting <code>target</code>'s <code>pageId</code> field to <code>"help"</code>.
|
|
The global page menu item's appearance is defined by setting the <code>title</code> field to the text that is to be displayed as a tooltip in the cluster menu.
|
|
The <code>components</code> field is used to set an icon that appears in the cluster menu.
|
|
Thus when the <code>"Help"</code> icon is activated the contents of <code>ExamplePage</code> will be shown.
|
|
This example requires the definition of another React-based component, <code>HelpIcon</code>, which has been added to <code>page.tsx</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span><span class="p">,</span> <span class="nx">Component</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="kd">function</span> <span class="nx">HelpIcon</span><span class="p">(</span><span class="nx">props</span>: <span class="kt">Component.IconProps</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">Icon</span> <span class="p">{...</span><span class="nx">props</span><span class="p">}</span> <span class="nx">material</span><span class="o">=</span><span class="s2">"help"</span><span class="o">/></span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">HelpPage</span> <span class="k">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="o"><</span><span class="p">{</span> <span class="nx">extension</span>: <span class="kt">LensRendererExtension</span> <span class="p">}</span><span class="o">></span> <span class="p">{</span>
|
|
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">p</span><span class="o">></span><span class="nx">Help</span><span class="o"><</span><span class="err">/p></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p><code>HelpIcon</code> introduces one of Lens's built-in components available to extension developers, the <code>Component.Icon</code>.
|
|
Built in are the <a href="https://material.io">Material Design</a> <a href="https://material.io/resources/icons/">icons</a>.
|
|
One can be selected by name via the <code>material</code> field.</p>
|
|
<h3 id="clusterfeatures"><code>clusterFeatures</code><a class="headerlink" href="#clusterfeatures" title="Permanent link">#</a></h3>
|
|
<p>Cluster features are Kubernetes resources that can be applied to and managed within the active cluster.
|
|
They can be installed/uninstalled by the Lens user from the <a href="">cluster settings page</a>.</p>
|
|
<p>The following example shows how to add a cluster feature as part of a <code>LensRendererExtension</code>:</p>
|
|
<p><div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">ExampleFeature</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./src/example-feature"</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">ExampleFeatureExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">clusterFeatures</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">title</span><span class="o">:</span> <span class="s2">"Example Feature"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Description</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">span</span><span class="o">></span>
|
|
<span class="nx">Enable</span> <span class="nx">an</span> <span class="nx">example</span> <span class="nx">feature</span><span class="p">.</span>
|
|
<span class="o"><</span><span class="err">/span></span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">feature</span>: <span class="kt">new</span> <span class="nx">ExampleFeature</span><span class="p">()</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
The <code>title</code> and <code>components.Description</code> fields provide content that appears on the cluster settings page, in the <strong>Features</strong> section.
|
|
The <code>feature</code> field must specify an instance which extends the abstract class <code>ClusterFeature.Feature</code>, and specifically implement the following methods:</p>
|
|
<div class="highlight"><pre><span></span><code> <span class="k">abstract</span> <span class="nx">install</span><span class="p">(</span><span class="nx">cluster</span>: <span class="kt">Cluster</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="k">void</span><span class="o">></span><span class="p">;</span>
|
|
<span class="k">abstract</span> <span class="nx">upgrade</span><span class="p">(</span><span class="nx">cluster</span>: <span class="kt">Cluster</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="k">void</span><span class="o">></span><span class="p">;</span>
|
|
<span class="k">abstract</span> <span class="nx">uninstall</span><span class="p">(</span><span class="nx">cluster</span>: <span class="kt">Cluster</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="k">void</span><span class="o">></span><span class="p">;</span>
|
|
<span class="k">abstract</span> <span class="nx">updateStatus</span><span class="p">(</span><span class="nx">cluster</span>: <span class="kt">Cluster</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="nx">ClusterFeatureStatus</span><span class="o">></span><span class="p">;</span>
|
|
</code></pre></div>
|
|
<p>The <code>install()</code> method is typically called by Lens when a user has indicated that this feature is to be installed (i.e. clicked <strong>Install</strong> for the feature on the cluster settings page).
|
|
The implementation of this method should install kubernetes resources using the <code>applyResources()</code> method, or by directly accessing the kubernetes api (<a href="tbd"><code>K8sApi</code></a>).</p>
|
|
<p>The <code>upgrade()</code> method is typically called by Lens when a user has indicated that this feature is to be upgraded (i.e. clicked <strong>Upgrade</strong> for the feature on the cluster settings page).
|
|
The implementation of this method should upgrade the kubernetes resources already installed, if relevant to the feature.</p>
|
|
<p>The <code>uninstall()</code> method is typically called by Lens when a user has indicated that this feature is to be uninstalled (i.e. clicked <strong>Uninstall</strong> for the feature on the cluster settings page).
|
|
The implementation of this method should uninstall kubernetes resources using the kubernetes api (<code>K8sApi</code>)</p>
|
|
<p>The <code>updateStatus()</code> method is called periodically by Lens to determine details about the feature's current status.
|
|
The implementation of this method should provide the current status information in the <code>status</code> field of the <code>ClusterFeature.Feature</code> parent class.
|
|
The <code>status.currentVersion</code> and <code>status.latestVersion</code> fields may be displayed by Lens in describing the feature.
|
|
The <code>status.installed</code> field should be set to true if the feature is currently installed, otherwise false.
|
|
Also, Lens relies on the <code>status.canUpgrade</code> field to determine if the feature can be upgraded (i.e a new version could be available) so the implementation should set the <code>status.canUpgrade</code> field according to specific rules for the feature, if relevant.</p>
|
|
<p>The following shows a very simple implementation of a <code>ClusterFeature</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">ClusterFeature</span><span class="p">,</span> <span class="nx">Store</span><span class="p">,</span> <span class="nx">K8sApi</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="o">*</span> <span class="kr">as</span> <span class="nx">path</span> <span class="k">from</span> <span class="s2">"path"</span><span class="p">;</span>
|
|
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">ExampleFeature</span> <span class="k">extends</span> <span class="nx">ClusterFeature</span><span class="p">.</span><span class="nx">Feature</span> <span class="p">{</span>
|
|
|
|
<span class="k">async</span> <span class="nx">install</span><span class="p">(</span><span class="nx">cluster</span>: <span class="kt">Store.Cluster</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="k">void</span><span class="o">></span> <span class="p">{</span>
|
|
|
|
<span class="k">super</span><span class="p">.</span><span class="nx">applyResources</span><span class="p">(</span><span class="nx">cluster</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="s2">"../resources/"</span><span class="p">));</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">async</span> <span class="nx">upgrade</span><span class="p">(</span><span class="nx">cluster</span>: <span class="kt">Store.Cluster</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="k">void</span><span class="o">></span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">install</span><span class="p">(</span><span class="nx">cluster</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">async</span> <span class="nx">updateStatus</span><span class="p">(</span><span class="nx">cluster</span>: <span class="kt">Store.Cluster</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="nx">ClusterFeature</span><span class="p">.</span><span class="nx">FeatureStatus</span><span class="o">></span> <span class="p">{</span>
|
|
<span class="k">try</span> <span class="p">{</span>
|
|
<span class="kd">const</span> <span class="nx">pod</span> <span class="o">=</span> <span class="nx">K8sApi</span><span class="p">.</span><span class="nx">forCluster</span><span class="p">(</span><span class="nx">cluster</span><span class="p">,</span> <span class="nx">K8sApi</span><span class="p">.</span><span class="nx">Pod</span><span class="p">);</span>
|
|
<span class="kd">const</span> <span class="nx">examplePod</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">pod</span><span class="p">.</span><span class="nx">get</span><span class="p">({</span><span class="nx">name</span><span class="o">:</span> <span class="s2">"example-pod"</span><span class="p">,</span> <span class="nx">namespace</span><span class="o">:</span> <span class="s2">"default"</span><span class="p">});</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">examplePod</span><span class="o">?</span><span class="p">.</span><span class="nx">kind</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">status</span><span class="p">.</span><span class="nx">installed</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">status</span><span class="p">.</span><span class="nx">currentVersion</span> <span class="o">=</span> <span class="nx">examplePod</span><span class="p">.</span><span class="nx">spec</span><span class="p">.</span><span class="nx">containers</span><span class="p">[</span><span class="mf">0</span><span class="p">].</span><span class="nx">image</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">)[</span><span class="mf">1</span><span class="p">];</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">status</span><span class="p">.</span><span class="nx">canUpgrade</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">// a real implementation would perform a check here that is relevant to the specific feature</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">status</span><span class="p">.</span><span class="nx">installed</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">status</span><span class="p">.</span><span class="nx">canUpgrade</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">e</span><span class="o">?</span><span class="p">.</span><span class="nx">error</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">===</span> <span class="mf">404</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">status</span><span class="p">.</span><span class="nx">installed</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">status</span><span class="p">.</span><span class="nx">canUpgrade</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">status</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">async</span> <span class="nx">uninstall</span><span class="p">(</span><span class="nx">cluster</span>: <span class="kt">Store.Cluster</span><span class="p">)</span><span class="o">:</span> <span class="nx">Promise</span><span class="o"><</span><span class="k">void</span><span class="o">></span> <span class="p">{</span>
|
|
<span class="kd">const</span> <span class="nx">podApi</span> <span class="o">=</span> <span class="nx">K8sApi</span><span class="p">.</span><span class="nx">forCluster</span><span class="p">(</span><span class="nx">cluster</span><span class="p">,</span> <span class="nx">K8sApi</span><span class="p">.</span><span class="nx">Pod</span><span class="p">);</span>
|
|
<span class="k">await</span> <span class="nx">podApi</span><span class="p">.</span><span class="k">delete</span><span class="p">({</span><span class="nx">name</span><span class="o">:</span> <span class="s2">"example-pod"</span><span class="p">,</span> <span class="nx">namespace</span><span class="o">:</span> <span class="s2">"default"</span><span class="p">});</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>This example implements the <code>install()</code> method by simply invoking the helper <code>applyResources()</code> method.
|
|
<code>applyResources()</code> tries to apply all resources read from all files found in the folder path provided.
|
|
In this case this folder path is the <code>../resources</code> subfolder relative to current source code's folder.
|
|
The file <code>../resources/example-pod.yml</code> could contain:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="nt">apiVersion</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">v1</span>
|
|
<span class="nt">kind</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">Pod</span>
|
|
<span class="nt">metadata</span><span class="p">:</span>
|
|
<span class="nt">name</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">example-pod</span>
|
|
<span class="nt">spec</span><span class="p">:</span>
|
|
<span class="nt">containers</span><span class="p">:</span>
|
|
<span class="p p-Indicator">-</span> <span class="nt">name</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">example-pod</span>
|
|
<span class="nt">image</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">nginx</span>
|
|
</code></pre></div>
|
|
<p>The <code>upgrade()</code> method in the example above is implemented by simply invoking the <code>install()</code> method.
|
|
Depending on the feature to be supported by an extension, upgrading may require additional and/or different steps.</p>
|
|
<p>The <code>uninstall()</code> method is implemented in the example above by utilizing the <a href="tbd"><code>K8sApi</code></a> provided by Lens to simply delete the <code>example-pod</code> pod applied by the <code>install()</code> method.</p>
|
|
<p>The <code>updateStatus()</code> method is implemented above by using the <a href="tbd"><code>K8sApi</code></a> as well, this time to get information from the <code>example-pod</code> pod, in particular to determine if it is installed, what version is associated with it, and if it can be upgraded.
|
|
How the status is updated for a specific cluster feature is up to the implementation.</p>
|
|
<h3 id="apppreferences"><code>appPreferences</code><a class="headerlink" href="#apppreferences" title="Permanent link">#</a></h3>
|
|
<p>The Preferences page is a built-in global page.
|
|
Extensions can add custom preferences to the Preferences page, thus providing a single location for users to configure global options, for Lens and extensions alike.
|
|
The following example demonstrates adding a custom preference:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">ExamplePreferenceHint</span><span class="p">,</span> <span class="nx">ExamplePreferenceInput</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./src/example-preference"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">observable</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"mobx"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span><span class="p">;</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">ExampleRendererExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
|
|
<span class="kd">@observable</span> <span class="nx">preference</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">enabled</span>: <span class="kt">false</span> <span class="p">};</span>
|
|
|
|
<span class="nx">appPreferences</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">title</span><span class="o">:</span> <span class="s2">"Example Preferences"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Input</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">ExamplePreferenceInput</span> <span class="nx">preference</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">preference</span><span class="p">}</span><span class="o">/></span><span class="p">,</span>
|
|
<span class="nx">Hint</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">ExamplePreferenceHint</span><span class="o">/></span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>App preferences are objects matching the <code>AppPreferenceRegistration</code> interface.
|
|
The <code>title</code> field specifies the text to show as the heading on the Preferences page.
|
|
The <code>components</code> field specifies two <code>React.Component</code> objects defining the interface for the preference.
|
|
<code>Input</code> should specify an interactive input element for your preference and <code>Hint</code> should provide descriptive information for the preference, which is shown below the <code>Input</code> element.
|
|
<code>ExamplePreferenceInput</code> expects its React props set to an <code>ExamplePreferenceProps</code> instance, which is how <code>ExampleRendererExtension</code> handles the state of the preference input.
|
|
<code>ExampleRendererExtension</code> has the field <code>preference</code>, which is provided to <code>ExamplePreferenceInput</code> when it is created.
|
|
In this example <code>ExamplePreferenceInput</code>, <code>ExamplePreferenceHint</code>, and <code>ExamplePreferenceProps</code> are defined in <code>./src/example-preference.tsx</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">Component</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">observer</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"mobx-react"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span><span class="p">;</span>
|
|
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">ExamplePreferenceProps</span> <span class="p">{</span>
|
|
<span class="nx">preference</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">enabled</span>: <span class="kt">boolean</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">@observer</span>
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">ExamplePreferenceInput</span> <span class="k">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="o"><</span><span class="nx">ExamplePreferenceProps</span><span class="o">></span> <span class="p">{</span>
|
|
|
|
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">const</span> <span class="p">{</span> <span class="nx">preference</span> <span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">Checkbox</span>
|
|
<span class="nx">label</span><span class="o">=</span><span class="s2">"I understand appPreferences"</span>
|
|
<span class="nx">value</span><span class="o">=</span><span class="p">{</span><span class="nx">preference</span><span class="p">.</span><span class="nx">enabled</span><span class="p">}</span>
|
|
<span class="nx">onChange</span><span class="o">=</span><span class="p">{</span><span class="nx">v</span> <span class="o">=></span> <span class="p">{</span> <span class="nx">preference</span><span class="p">.</span><span class="nx">enabled</span> <span class="o">=</span> <span class="nx">v</span><span class="p">;</span> <span class="p">}}</span>
|
|
<span class="o">/></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">ExamplePreferenceHint</span> <span class="k">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span> <span class="p">{</span>
|
|
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">span</span><span class="o">></span><span class="nx">This</span> <span class="nx">is</span> <span class="nx">an</span> <span class="nx">example</span> <span class="k">of</span> <span class="nx">an</span> <span class="nx">appPreference</span> <span class="k">for</span> <span class="nx">extensions</span><span class="p">.</span><span class="o"><</span><span class="err">/span></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p><code>ExamplePreferenceInput</code> implements a simple checkbox (using Lens's <code>Component.Checkbox</code>).
|
|
It provides <code>label</code> as the text to display next to the checkbox and an <code>onChange</code> function, which reacts to the checkbox state change.
|
|
The checkbox's <code>value</code> is initially set to <code>preference.enabled</code>.
|
|
<code>ExamplePreferenceInput</code> is defined with React props of <code>ExamplePreferenceProps</code> type, which is an object with a single field, <code>enabled</code>.
|
|
This is used to indicate the state of the preference, and is bound to the checkbox state in <code>onChange</code>.
|
|
<code>ExamplePreferenceHint</code> is a simple text span.
|
|
Note that the input and the hint could comprise of more sophisticated elements, according to the needs of the extension.</p>
|
|
<p>Note that the above example introduces decorators <code>observable</code> and <code>observer</code> from the <a href="https://mobx.js.org/README.html"><code>mobx</code></a> and <a href="https://github.com/mobxjs/mobx-react#mobx-react"><code>mobx-react</code></a> packages.
|
|
<code>mobx</code> simplifies state management and without it this example would not visually update the checkbox properly when the user activates it.
|
|
<a href="../working-with-mobx">Lens uses <code>mobx</code> extensively for state management</a> of its own UI elements and it is recommended that extensions rely on it too.
|
|
Alternatively, React's state management can be used, though <code>mobx</code> is typically simpler to use.</p>
|
|
<p>Also note that an extension's state data can be managed using an <code>ExtensionStore</code> object, which conveniently handles persistence and synchronization.
|
|
The example above defined a <code>preference</code> field in the <code>ExampleRendererExtension</code> class definition to hold the extension's state primarily to simplify the code for this guide, but it is recommended to manage your extension's state data using <a href="../stores#extensionstore"><code>ExtensionStore</code></a></p>
|
|
<h3 id="statusbaritems"><code>statusBarItems</code><a class="headerlink" href="#statusbaritems" title="Permanent link">#</a></h3>
|
|
<p>The Status bar is the blue strip along the bottom of the Lens UI.
|
|
Status bar items are <code>React.ReactNode</code> types, which can be used to convey status information, or act as a link to a global page, or even an external page.</p>
|
|
<p>The following example adds a status bar item definition, as well as a global page definition, to a <code>LensRendererExtension</code> subclass, and configures the status bar item to navigate to the global page upon activation (normally a mouse click):</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s1">'@k8slens/extensions'</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">HelpIcon</span><span class="p">,</span> <span class="nx">HelpPage</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./page"</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s1">'react'</span><span class="p">;</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">HelpExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">globalPages</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">id</span><span class="o">:</span> <span class="s2">"help"</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Page</span><span class="o">:</span> <span class="p">()</span> <span class="o">=></span> <span class="o"><</span><span class="nx">HelpPage</span> <span class="nx">extension</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">}</span><span class="o">/></span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
|
|
<span class="nx">statusBarItems</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">item</span><span class="o">:</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span>
|
|
<span class="nx">className</span><span class="o">=</span><span class="s2">"flex align-center gaps"</span>
|
|
<span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=></span> <span class="k">this</span><span class="p">.</span><span class="nx">navigate</span><span class="p">(</span><span class="s2">"help"</span><span class="p">)}</span>
|
|
<span class="o">></span>
|
|
<span class="o"><</span><span class="nx">HelpIcon</span> <span class="o">/></span>
|
|
<span class="nx">My</span> <span class="nx">Status</span> <span class="nx">Bar</span> <span class="nx">Item</span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">),</span>
|
|
<span class="p">},</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>The <code>item</code> field of a status bar item specifies the <code>React.Component</code> to be shown on the status bar.
|
|
By default items are added starting from the right side of the status bar.
|
|
Typically, <code>item</code> would specify an icon and/or a short string of text, considering the limited space on the status bar.
|
|
In the example above the <code>HelpIcon</code> from the <a href="#globalpagemenus"><code>globalPageMenus</code> guide</a> is reused.
|
|
Also, the <code>item</code> provides a link to the global page by setting the <code>onClick</code> property to a function that calls the <code>LensRendererExtension</code> <code>navigate()</code> method.
|
|
<code>navigate()</code> takes as a parameter the id of the global page, which is shown when <code>navigate()</code> is called.</p>
|
|
<h3 id="kubeobjectmenuitems"><code>kubeObjectMenuItems</code><a class="headerlink" href="#kubeobjectmenuitems" title="Permanent link">#</a></h3>
|
|
<p>An extension can add custom menu items (including actions) for specific Kubernetes resource kinds/apiVersions.
|
|
These menu items appear under the <code>...</code> for each listed resource in the cluster dashboard, and on the title bar of the details page for a specific resource:</p>
|
|
<p><img alt="List" src="../images/kubeobjectmenuitem.png" /></p>
|
|
<p><img alt="Details" src="../images/kubeobjectmenuitemdetail.png" /></p>
|
|
<p>The following example shows how to add a menu for Namespace resources, and associate an action with it:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">NamespaceMenuItem</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./src/namespace-menu-item"</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">ExampleExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">kubeObjectMenuItems</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">kind</span><span class="o">:</span> <span class="s2">"Namespace"</span><span class="p">,</span>
|
|
<span class="nx">apiVersions</span><span class="o">:</span> <span class="p">[</span><span class="s2">"v1"</span><span class="p">],</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">MenuItem</span><span class="o">:</span> <span class="p">(</span><span class="nx">props</span>: <span class="kt">Component.KubeObjectMenuProps</span><span class="o"><</span><span class="nx">K8sApi</span><span class="p">.</span><span class="nx">Namespace</span><span class="o">></span><span class="p">)</span> <span class="o">=></span> <span class="o"><</span><span class="nx">NamespaceMenuItem</span> <span class="p">{...</span><span class="nx">props</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Kube object menu items are objects matching the <code>KubeObjectMenuRegistration</code> interface.
|
|
The <code>kind</code> field specifies the kubernetes resource type to apply this menu item to, and the <code>apiVersion</code> field specifies the kubernetes api to use in relation to this resource type.
|
|
This example adds a menu item for namespaces in the cluster dashboard.
|
|
The <code>components</code> field defines the menu item's appearance and behaviour.
|
|
The <code>MenuItem</code> field provides a function that returns a <code>React.Component</code> given a set of menu item properties.
|
|
In this example a <code>NamespaceMenuItem</code> object is returned.
|
|
<code>NamespaceMenuItem</code> is defined in <code>./src/namespace-menu-item.tsx</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">Component</span><span class="p">,</span> <span class="nx">K8sApi</span><span class="p">,</span> <span class="nx">Navigation</span><span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
|
|
<span class="k">export</span> <span class="kd">function</span> <span class="nx">NamespaceMenuItem</span><span class="p">(</span><span class="nx">props</span>: <span class="kt">Component.KubeObjectMenuProps</span><span class="o"><</span><span class="nx">K8sApi</span><span class="p">.</span><span class="nx">Namespace</span><span class="o">></span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">const</span> <span class="p">{</span> <span class="nx">object</span>: <span class="kt">namespace</span><span class="p">,</span> <span class="nx">toolbar</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">props</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">namespace</span><span class="p">)</span> <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
|
|
|
|
<span class="kd">const</span> <span class="nx">namespaceName</span> <span class="o">=</span> <span class="nx">namespace</span><span class="p">.</span><span class="nx">getName</span><span class="p">();</span>
|
|
|
|
<span class="kd">const</span> <span class="nx">sendToTerminal</span> <span class="o">=</span> <span class="p">(</span><span class="nx">command</span>: <span class="kt">string</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
|
|
<span class="nx">Component</span><span class="p">.</span><span class="nx">terminalStore</span><span class="p">.</span><span class="nx">sendCommand</span><span class="p">(</span><span class="nx">command</span><span class="p">,</span> <span class="p">{</span>
|
|
<span class="nx">enter</span>: <span class="kt">true</span><span class="p">,</span>
|
|
<span class="nx">newTab</span>: <span class="kt">true</span><span class="p">,</span>
|
|
<span class="p">});</span>
|
|
<span class="nx">Navigation</span><span class="p">.</span><span class="nx">hideDetails</span><span class="p">();</span>
|
|
<span class="p">};</span>
|
|
|
|
<span class="kd">const</span> <span class="nx">getPods</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
|
|
<span class="nx">sendToTerminal</span><span class="p">(</span><span class="sb">`kubectl get pods -n </span><span class="si">${</span><span class="nx">namespaceName</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
|
|
<span class="p">};</span>
|
|
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">MenuItem</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{</span><span class="nx">getPods</span><span class="p">}</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">Icon</span> <span class="nx">material</span><span class="o">=</span><span class="s2">"speaker_group"</span> <span class="nx">interactive</span><span class="o">=</span><span class="p">{</span><span class="nx">toolbar</span><span class="p">}</span> <span class="nx">title</span><span class="o">=</span><span class="s2">"Get pods in terminal"</span><span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">span</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"title"</span><span class="o">></span><span class="nx">Get</span> <span class="nx">Pods</span><span class="o"><</span><span class="err">/span></span>
|
|
<span class="o"><</span><span class="err">/Component.MenuItem></span>
|
|
<span class="p">);</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p><code>NamespaceMenuItem</code> returns a <code>Component.MenuItem</code> defining the menu item's appearance (icon and text) and behaviour when activated via the <code>onClick</code> property.
|
|
<code>getPods()</code> shows how to open a terminal tab and run a command, specifically it runs <code>kubectl</code> to get a list of pods running in the current namespace.
|
|
See <a href="api-docs?"><code>Component.terminalStore.sendCommand</code></a> for more details on running terminal commands.
|
|
The name of the namespace is retrieved from <code>props</code> passed into <code>NamespaceMenuItem()</code>.
|
|
<code>namespace</code> is the <code>props.object</code>, which is of type <code>K8sApi.Namespace</code>.
|
|
This is the api for accessing namespaces, and the current namespace in this example is simply given by <code>namespace.getName()</code>.
|
|
Thus kube object menu items are afforded convenient access to the specific resource selected by the user.</p>
|
|
<h3 id="kubeobjectdetailitems"><code>kubeObjectDetailItems</code><a class="headerlink" href="#kubeobjectdetailitems" title="Permanent link">#</a></h3>
|
|
<p>An extension can add custom details (content) for specified Kubernetes resource kinds/apiVersions.
|
|
These custom details appear on the details page for a specific resource, such as a Namespace:</p>
|
|
<p><img alt="Details" src="../images/kubeobjectdetailitem.png" /></p>
|
|
<p>The following example shows how to add a tabulated list of pods to the Namespace resource details page:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">LensRendererExtension</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">NamespaceDetailsItem</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./src/namespace-details-item"</span>
|
|
|
|
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">ExampleExtension</span> <span class="k">extends</span> <span class="nx">LensRendererExtension</span> <span class="p">{</span>
|
|
<span class="nx">kubeObjectDetailItems</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">kind</span><span class="o">:</span> <span class="s2">"Namespace"</span><span class="p">,</span>
|
|
<span class="nx">apiVersions</span><span class="o">:</span> <span class="p">[</span><span class="s2">"v1"</span><span class="p">],</span>
|
|
<span class="nx">priority</span>: <span class="kt">10</span><span class="p">,</span>
|
|
<span class="nx">components</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">Details</span><span class="o">:</span> <span class="p">(</span><span class="nx">props</span>: <span class="kt">Component.KubeObjectDetailsProps</span><span class="o"><</span><span class="nx">K8sApi</span><span class="p">.</span><span class="nx">Namespace</span><span class="o">></span><span class="p">)</span> <span class="o">=></span> <span class="o"><</span><span class="nx">NamespaceDetailsItem</span> <span class="p">{...</span><span class="nx">props</span><span class="p">}</span> <span class="o">/></span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">];</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Kube object detail items are objects matching the <code>KubeObjectDetailRegistration</code> interface.
|
|
The <code>kind</code> field specifies the kubernetes resource type to apply this detail item to, and the <code>apiVersion</code> field specifies the kubernetes api to use in relation to this resource type.
|
|
This example adds a detail item for namespaces in the cluster dashboard.
|
|
The <code>components</code> field defines the detail item's appearance and behaviour.
|
|
The <code>Details</code> field provides a function that returns a <code>React.Component</code> given a set of detail item properties.
|
|
In this example a <code>NamespaceDetailsItem</code> object is returned.
|
|
<code>NamespaceDetailsItem</code> is defined in <code>./src/namespace-details-item.tsx</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="p">{</span> <span class="nx">Component</span><span class="p">,</span> <span class="nx">K8sApi</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">PodsDetailsList</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./pods-details-list"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">observable</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"mobx"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">observer</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"mobx-react"</span><span class="p">;</span>
|
|
|
|
<span class="kd">@observer</span>
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">NamespaceDetailsItem</span> <span class="k">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">KubeObjectDetailsProps</span><span class="o"><</span><span class="nx">K8sApi</span><span class="p">.</span><span class="nx">Namespace</span><span class="o">>></span> <span class="p">{</span>
|
|
|
|
<span class="kd">@observable</span> <span class="k">private</span> <span class="nx">pods</span>: <span class="kt">K8sApi.Pod</span><span class="p">[];</span>
|
|
|
|
<span class="k">async</span> <span class="nx">componentDidMount</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">pods</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">K8sApi</span><span class="p">.</span><span class="nx">podsApi</span><span class="p">.</span><span class="nx">list</span><span class="p">({</span><span class="nx">namespace</span>: <span class="kt">this.props.object.getName</span><span class="p">()});</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">DrawerTitle</span> <span class="nx">title</span><span class="o">=</span><span class="s2">"Pods"</span> <span class="o">/></span>
|
|
<span class="o"><</span><span class="nx">PodsDetailsList</span> <span class="nx">pods</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">pods</span><span class="p">}</span><span class="o">/></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Since <code>NamespaceDetailsItem</code> extends <code>React.Component<Component.KubeObjectDetailsProps<K8sApi.Namespace>></code> it can access the current namespace object (type <code>K8sApi.Namespace</code>) through <code>this.props.object</code>.
|
|
This object can be queried for many details about the current namespace.
|
|
In this example the namespace's name is obtained in <code>componentDidMount()</code> using the <code>K8sApi.Namespace</code> <code>getName()</code> method.
|
|
The namespace's name is needed to limit the list of pods to only those in this namespace.
|
|
To get the list of pods this example uses the kubernetes pods api, specifically the <code>K8sApi.podsApi.list()</code> method.
|
|
The <code>K8sApi.podsApi</code> is automatically configured for the currently active cluster.</p>
|
|
<p>Note that <code>K8sApi.podsApi.list()</code> is an asynchronous method, and ideally getting the pods list should be done before rendering the <code>NamespaceDetailsItem</code>.
|
|
It is a common technique in React development to await async calls in <code>componentDidMount()</code>.
|
|
However, <code>componentDidMount()</code> is called right after the first call to <code>render()</code>.
|
|
In order to effect a subsequent <code>render()</code> call React must be made aware of a state change.
|
|
Like in the <a href="#apppreferences"><code>appPreferences</code> guide</a>, <a href="https://mobx.js.org/README.html"><code>mobx</code></a> and <a href="https://github.com/mobxjs/mobx-react#mobx-react"><code>mobx-react</code></a> are used to ensure <code>NamespaceDetailsItem</code> renders when the pods list is updated.
|
|
This is done simply by marking the <code>pods</code> field as an <code>observable</code> and the <code>NamespaceDetailsItem</code> class itself as an <code>observer</code>.</p>
|
|
<p>Finally, the <code>NamespaceDetailsItem</code> is rendered using the <code>render()</code> method.
|
|
Details are placed in drawers, and using <code>Component.DrawerTitle</code> provides a separator from details above this one.
|
|
Multiple details in a drawer can be placed in <code><Component.DrawerItem></code> elements for further separation, if desired.
|
|
The rest of this example's details are defined in <code>PodsDetailsList</code>, found in <code>./pods-details-list.tsx</code>:</p>
|
|
<div class="highlight"><pre><span></span><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span><span class="p">;</span>
|
|
<span class="k">import</span> <span class="p">{</span> <span class="nx">Component</span><span class="p">,</span> <span class="nx">K8sApi</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"@k8slens/extensions"</span><span class="p">;</span>
|
|
|
|
<span class="kd">interface</span> <span class="nx">Props</span> <span class="p">{</span>
|
|
<span class="nx">pods</span>: <span class="kt">K8sApi.Pod</span><span class="p">[];</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">export</span> <span class="kd">class</span> <span class="nx">PodsDetailsList</span> <span class="k">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="o"><</span><span class="nx">Props</span><span class="o">></span> <span class="p">{</span>
|
|
|
|
<span class="nx">getTableRow</span><span class="p">(</span><span class="nx">index</span>: <span class="kt">number</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">const</span> <span class="p">{</span><span class="nx">pods</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">TableRow</span> <span class="nx">key</span><span class="o">=</span><span class="p">{</span><span class="nx">index</span><span class="p">}</span> <span class="nx">nowrap</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">TableCell</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"podName"</span><span class="o">></span><span class="p">{</span><span class="nx">pods</span><span class="p">[</span><span class="nx">index</span><span class="p">].</span><span class="nx">getName</span><span class="p">()}</span><span class="o"><</span><span class="err">/Component.TableCell></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">TableCell</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"podAge"</span><span class="o">></span><span class="p">{</span><span class="nx">pods</span><span class="p">[</span><span class="nx">index</span><span class="p">].</span><span class="nx">getAge</span><span class="p">()}</span><span class="o"><</span><span class="err">/Component.TableCell></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">TableCell</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"podStatus"</span><span class="o">></span><span class="p">{</span><span class="nx">pods</span><span class="p">[</span><span class="nx">index</span><span class="p">].</span><span class="nx">getStatus</span><span class="p">()}</span><span class="o"><</span><span class="err">/Component.TableCell></span>
|
|
<span class="o"><</span><span class="err">/Component.TableRow></span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">const</span> <span class="p">{</span><span class="nx">pods</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">pods</span><span class="o">?</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">return</span> <span class="p">(</span>
|
|
<span class="o"><</span><span class="nx">div</span> <span class="o">></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">Table</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">TableHead</span><span class="o">></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">TableCell</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"podName"</span><span class="o">></span><span class="nx">Name</span><span class="o"><</span><span class="err">/Component.TableCell></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">TableCell</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"podAge"</span><span class="o">></span><span class="nx">Age</span><span class="o"><</span><span class="err">/Component.TableCell></span>
|
|
<span class="o"><</span><span class="nx">Component</span><span class="p">.</span><span class="nx">TableCell</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"podStatus"</span><span class="o">></span><span class="nx">Status</span><span class="o"><</span><span class="err">/Component.TableCell></span>
|
|
<span class="o"><</span><span class="err">/Component.TableHead></span>
|
|
<span class="p">{</span>
|
|
<span class="nx">pods</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">pod</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">=></span> <span class="k">this</span><span class="p">.</span><span class="nx">getTableRow</span><span class="p">(</span><span class="nx">index</span><span class="p">))</span>
|
|
<span class="p">}</span>
|
|
<span class="o"><</span><span class="err">/Component.Table></span>
|
|
<span class="o"><</span><span class="err">/div></span>
|
|
<span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p><code>PodsDetailsList</code> produces a simple table showing a list of the pods found in this namespace:</p>
|
|
<p><img alt="DetailsWithPods" src="../images/kubeobjectdetailitemwithpods.png" /></p>
|
|
<p>For each pod the name, age, and status are obtained using the <code>K8sApi.Pod</code> methods.
|
|
The table is constructed using the <code>Component.Table</code> and related elements.
|
|
See <a href="url?"><code>Component</code> documentation</a> for further details.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</article>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
|
|
<footer class="md-footer">
|
|
|
|
<div class="md-footer-nav">
|
|
<nav class="md-footer-nav__inner md-grid" aria-label="Footer">
|
|
|
|
<a href="../main-extension/" class="md-footer-nav__link md-footer-nav__link--prev" rel="prev">
|
|
<div class="md-footer-nav__button md-icon">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
|
|
</div>
|
|
<div class="md-footer-nav__title">
|
|
<div class="md-ellipsis">
|
|
<span class="md-footer-nav__direction">
|
|
Previous
|
|
</span>
|
|
Main Extension
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
|
|
<a href="../stores/" class="md-footer-nav__link md-footer-nav__link--next" rel="next">
|
|
<div class="md-footer-nav__title">
|
|
<div class="md-ellipsis">
|
|
<span class="md-footer-nav__direction">
|
|
Next
|
|
</span>
|
|
Stores
|
|
</div>
|
|
</div>
|
|
<div class="md-footer-nav__button md-icon">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z"/></svg>
|
|
</div>
|
|
</a>
|
|
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="md-footer-meta md-typeset">
|
|
<div class="md-footer-meta__inner md-grid">
|
|
<div class="md-footer-copyright">
|
|
|
|
<div class="md-footer-copyright__highlight">
|
|
Copyright © 2021 <a href="https://mirantis.com/">Mirantis Inc.</a> - All rights reserved.
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
<div class="md-footer-social">
|
|
|
|
|
|
|
|
<a href="https://github.com/lensapp/lens" target="_blank" rel="noopener" title="Lens on GitHub" class="md-footer-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
<a href="https://twitter.com/k8slens" target="_blank" rel="noopener" title="Lens on Twitter" class="md-footer-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
<a href="http://k8slens.slack.com/" target="_blank" rel="noopener" title="Lens on Slack" class="md-footer-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M94.12 315.1c0 25.9-21.16 47.06-47.06 47.06S0 341 0 315.1c0-25.9 21.16-47.06 47.06-47.06h47.06v47.06zm23.72 0c0-25.9 21.16-47.06 47.06-47.06s47.06 21.16 47.06 47.06v117.84c0 25.9-21.16 47.06-47.06 47.06s-47.06-21.16-47.06-47.06V315.1zm47.06-188.98c-25.9 0-47.06-21.16-47.06-47.06S139 32 164.9 32s47.06 21.16 47.06 47.06v47.06H164.9zm0 23.72c25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06H47.06C21.16 243.96 0 222.8 0 196.9s21.16-47.06 47.06-47.06H164.9zm188.98 47.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06h-47.06V196.9zm-23.72 0c0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06V79.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06V196.9zM283.1 385.88c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06v-47.06h47.06zm0-23.72c-25.9 0-47.06-21.16-47.06-47.06 0-25.9 21.16-47.06 47.06-47.06h117.84c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06H283.1z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
<a href="https://k8slens.dev/" target="_blank" rel="noopener" title="Lens Website" class="md-footer-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 01-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0120.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0020.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 00-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
</div>
|
|
|
|
<script src="../../../assets/javascripts/vendor.4d7724a9.min.js"></script>
|
|
<script src="../../../assets/javascripts/bundle.0421a6ad.min.js"></script><script id="__lang" type="application/json">{"clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.term.missing": "Missing"}</script>
|
|
|
|
<script>
|
|
app = initialize({
|
|
base: "../../..",
|
|
features: ['toc.autohide', 'search.suggest', 'search.highlight'],
|
|
search: Object.assign({
|
|
worker: "../../../assets/javascripts/worker/search.0f64ce30.min.js"
|
|
}, typeof search !== "undefined" && search),
|
|
version: {'method': 'mike'}
|
|
})
|
|
</script>
|
|
|
|
|
|
</body>
|
|
</html> |