mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fully support displaying all supported PodVolume types (#4131)
This commit is contained in:
parent
b3574e1a21
commit
4c92f3f251
@ -6,29 +6,29 @@ The Renderer Extension API allows you to access, configure, and customize Lens d
|
|||||||
|
|
||||||
The custom Lens UI elements that you can add include:
|
The custom Lens UI elements that you can add include:
|
||||||
|
|
||||||
* [Cluster pages](#clusterpages)
|
- [Cluster pages](#clusterpages)
|
||||||
* [Cluster page menus](#clusterpagemenus)
|
- [Cluster page menus](#clusterpagemenus)
|
||||||
* [Global pages](#globalpages)
|
- [Global pages](#globalpages)
|
||||||
* [Welcome menus](#welcomemenus)
|
- [Welcome menus](#welcomemenus)
|
||||||
* [App preferences](#apppreferences)
|
- [App preferences](#apppreferences)
|
||||||
* [Top bar items](#topbaritems)
|
- [Top bar items](#topbaritems)
|
||||||
* [Status bar items](#statusbaritems)
|
- [Status bar items](#statusbaritems)
|
||||||
* [KubeObject menu items](#kubeobjectmenuitems)
|
- [KubeObject menu items](#kubeobjectmenuitems)
|
||||||
* [KubeObject detail items](#kubeobjectdetailitems)
|
- [KubeObject detail items](#kubeobjectdetailitems)
|
||||||
* [KubeObject status texts](#kubeobjectstatustexts)
|
- [KubeObject status texts](#kubeobjectstatustexts)
|
||||||
* [Kube workloads overview items](#kubeworkloadsoverviewitems)
|
- [Kube workloads overview items](#kubeworkloadsoverviewitems)
|
||||||
|
|
||||||
as well as catalog-related UI elements:
|
as well as catalog-related UI elements:
|
||||||
|
|
||||||
* [Entity settings](#entitysettings)
|
- [Entity settings](#entitysettings)
|
||||||
* [Catalog entity detail items](#catalogentitydetailitems)
|
- [Catalog entity detail items](#catalogentitydetailitems)
|
||||||
|
|
||||||
All UI elements are based on React components.
|
All UI elements are based on React components.
|
||||||
|
|
||||||
Finally, you can also add commands and protocol handlers:
|
Finally, you can also add commands and protocol handlers:
|
||||||
|
|
||||||
* [Command palette commands](#commandpalettecommands)
|
- [Command palette commands](#commandpalettecommands)
|
||||||
* [protocol handlers](protocol-handlers.md)
|
- [protocol handlers](protocol-handlers.md)
|
||||||
|
|
||||||
## `Renderer.LensExtension` Class
|
## `Renderer.LensExtension` Class
|
||||||
|
|
||||||
@ -41,11 +41,11 @@ import { Renderer } from "@k8slens/extensions";
|
|||||||
|
|
||||||
export default class ExampleExtensionMain extends Renderer.LensExtension {
|
export default class ExampleExtensionMain extends Renderer.LensExtension {
|
||||||
onActivate() {
|
onActivate() {
|
||||||
console.log('custom renderer process extension code started');
|
console.log("custom renderer process extension code started");
|
||||||
}
|
}
|
||||||
|
|
||||||
onDeactivate() {
|
onDeactivate() {
|
||||||
console.log('custom renderer process extension de-activated');
|
console.log("custom renderer process extension de-activated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -56,7 +56,7 @@ You can initiate custom code by implementing `onActivate()`.
|
|||||||
Implementing `onDeactivate()` gives you the opportunity to clean up after your extension.
|
Implementing `onDeactivate()` gives you the opportunity to clean up after your extension.
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
Disable extensions from the Lens Extensions page:
|
Disable extensions from the Lens Extensions page:
|
||||||
|
|
||||||
1. Navigate to **File** > **Extensions** in the top menu bar.
|
1. Navigate to **File** > **Extensions** in the top menu bar.
|
||||||
(On Mac, it is **Lens** > **Extensions**.)
|
(On Mac, it is **Lens** > **Extensions**.)
|
||||||
@ -75,17 +75,17 @@ Add a cluster page definition to a `Renderer.LensExtension` subclass with the fo
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { ExampleIcon, ExamplePage } from "./page"
|
import { ExampleIcon, ExamplePage } from "./page";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export default class ExampleExtension extends Renderer.LensExtension {
|
export default class ExampleExtension extends Renderer.LensExtension {
|
||||||
clusterPages = [
|
clusterPages = [
|
||||||
{
|
{
|
||||||
id: "hello",
|
id: "hello",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <ExamplePage extension={this}/>,
|
Page: () => <ExamplePage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -93,24 +93,26 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
`clusterPages` is an array of objects that satisfy the `PageRegistration` interface.
|
`clusterPages` is an array of objects that satisfy the `PageRegistration` interface.
|
||||||
The properties of the `clusterPages` array objects are defined as follows:
|
The properties of the `clusterPages` array objects are defined as follows:
|
||||||
|
|
||||||
* `id` is a string that identifies the page.
|
- `id` is a string that identifies the page.
|
||||||
* `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
- `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
||||||
* `Page` is of type ` React.ComponentType<any>`.
|
- `Page` is of type ` React.ComponentType<any>`.
|
||||||
It offers flexibility in defining the appearance and behavior of your page.
|
It offers flexibility in defining the appearance and behavior of your page.
|
||||||
|
|
||||||
`ExamplePage` in the example above can be defined in `page.tsx`:
|
`ExamplePage` in the example above can be defined in `page.tsx`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export class ExamplePage extends React.Component<{ extension: LensRendererExtension }> {
|
export class ExamplePage extends React.Component<{
|
||||||
|
extension: LensRendererExtension;
|
||||||
|
}> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Hello world!</p>
|
<p>Hello world!</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -130,17 +132,17 @@ By expanding on the above example, you can add a cluster page menu item to the `
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { ExampleIcon, ExamplePage } from "./page"
|
import { ExampleIcon, ExamplePage } from "./page";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export default class ExampleExtension extends Renderer.LensExtension {
|
export default class ExampleExtension extends Renderer.LensExtension {
|
||||||
clusterPages = [
|
clusterPages = [
|
||||||
{
|
{
|
||||||
id: "hello",
|
id: "hello",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <ExamplePage extension={this}/>,
|
Page: () => <ExamplePage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
clusterPageMenus = [
|
clusterPageMenus = [
|
||||||
@ -149,7 +151,7 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
title: "Hello World",
|
title: "Hello World",
|
||||||
components: {
|
components: {
|
||||||
Icon: ExampleIcon,
|
Icon: ExampleIcon,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -159,10 +161,10 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
This element defines how the cluster page menu item will appear and what it will do when you click it.
|
This element defines how the cluster page menu item will appear and what it will do when you click it.
|
||||||
The properties of the `clusterPageMenus` array objects are defined as follows:
|
The properties of the `clusterPageMenus` array objects are defined as follows:
|
||||||
|
|
||||||
* `target` links to the relevant cluster page using `pageId`.
|
- `target` links to the relevant cluster page using `pageId`.
|
||||||
* `pageId` takes the value of the relevant cluster page's `id` property.
|
- `pageId` takes the value of the relevant cluster page's `id` property.
|
||||||
* `title` sets the name of the cluster page menu item that will appear in the left side menu.
|
- `title` sets the name of the cluster page menu item that will appear in the left side menu.
|
||||||
* `components` is used to set an icon that appears to the left of the `title` text in the left side menu.
|
- `components` is used to set an icon that appears to the left of the `title` text in the left side menu.
|
||||||
|
|
||||||
The above example creates a menu item that reads **Hello World**.
|
The above example creates a menu item that reads **Hello World**.
|
||||||
When users click **Hello World**, the cluster dashboard will show the contents of `Example Page`.
|
When users click **Hello World**, the cluster dashboard will show the contents of `Example Page`.
|
||||||
@ -171,7 +173,7 @@ This example requires the definition of another React-based component, `ExampleI
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
type IconProps = Renderer.Component.IconProps;
|
type IconProps = Renderer.Component.IconProps;
|
||||||
|
|
||||||
@ -180,16 +182,18 @@ const {
|
|||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
export function ExampleIcon(props: IconProps) {
|
export function ExampleIcon(props: IconProps) {
|
||||||
return <Icon {...props} material="pages" tooltip={"Hi!"}/>
|
return <Icon {...props} material="pages" tooltip={"Hi!"} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExamplePage extends React.Component<{ extension: Renderer.LensExtension }> {
|
export class ExamplePage extends React.Component<{
|
||||||
|
extension: Renderer.LensExtension;
|
||||||
|
}> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Hello world!</p>
|
<p>Hello world!</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -198,32 +202,31 @@ Lens includes various built-in components available for extension developers to
|
|||||||
One of these is the `Renderer.Component.Icon`, introduced in `ExampleIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io).
|
One of these is the `Renderer.Component.Icon`, introduced in `ExampleIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io).
|
||||||
The properties that `Renderer.Component.Icon` uses are defined as follows:
|
The properties that `Renderer.Component.Icon` uses are defined as follows:
|
||||||
|
|
||||||
* `material` takes the name of the icon you want to use.
|
- `material` takes the name of the icon you want to use.
|
||||||
* `tooltip` sets the text you want to appear when a user hovers over the icon.
|
- `tooltip` sets the text you want to appear when a user hovers over the icon.
|
||||||
|
|
||||||
`clusterPageMenus` can also be used to define sub menu items, so that you can create groups of cluster pages.
|
`clusterPageMenus` can also be used to define sub menu items, so that you can create groups of cluster pages.
|
||||||
The following example groups two sub menu items under one parent menu item:
|
The following example groups two sub menu items under one parent menu item:
|
||||||
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { ExampleIcon, ExamplePage } from "./page"
|
import { ExampleIcon, ExamplePage } from "./page";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export default class ExampleExtension extends Renderer.LensExtension {
|
export default class ExampleExtension extends Renderer.LensExtension {
|
||||||
clusterPages = [
|
clusterPages = [
|
||||||
{
|
{
|
||||||
id: "hello",
|
id: "hello",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <ExamplePage extension={this}/>,
|
Page: () => <ExamplePage extension={this} />,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "bonjour",
|
id: "bonjour",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <ExemplePage extension={this}/>,
|
Page: () => <ExemplePage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
clusterPageMenus = [
|
clusterPageMenus = [
|
||||||
@ -232,7 +235,7 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
title: "Greetings",
|
title: "Greetings",
|
||||||
components: {
|
components: {
|
||||||
Icon: ExampleIcon,
|
Icon: ExampleIcon,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
parentId: "example",
|
parentId: "example",
|
||||||
@ -240,7 +243,7 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
title: "Hello World",
|
title: "Hello World",
|
||||||
components: {
|
components: {
|
||||||
Icon: ExampleIcon,
|
Icon: ExampleIcon,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
parentId: "example",
|
parentId: "example",
|
||||||
@ -248,8 +251,8 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
title: "Bonjour le monde",
|
title: "Bonjour le monde",
|
||||||
components: {
|
components: {
|
||||||
Icon: ExempleIcon,
|
Icon: ExempleIcon,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -280,18 +283,18 @@ Unlike cluster pages, users can trigger global pages even when there is no activ
|
|||||||
The following example defines a `Renderer.LensExtension` subclass with a single global page definition:
|
The following example defines a `Renderer.LensExtension` subclass with a single global page definition:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from '@k8slens/extensions';
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { HelpPage } from './page';
|
import { HelpPage } from "./page";
|
||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
export default class HelpExtension extends Renderer.LensExtension {
|
export default class HelpExtension extends Renderer.LensExtension {
|
||||||
globalPages = [
|
globalPages = [
|
||||||
{
|
{
|
||||||
id: "help",
|
id: "help",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <HelpPage extension={this}/>,
|
Page: () => <HelpPage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -299,24 +302,26 @@ export default class HelpExtension extends Renderer.LensExtension {
|
|||||||
`globalPages` is an array of objects that satisfy the `PageRegistration` interface.
|
`globalPages` is an array of objects that satisfy the `PageRegistration` interface.
|
||||||
The properties of the `globalPages` array objects are defined as follows:
|
The properties of the `globalPages` array objects are defined as follows:
|
||||||
|
|
||||||
* `id` is a string that identifies the page.
|
- `id` is a string that identifies the page.
|
||||||
* `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
- `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
||||||
* `Page` is of type `React.ComponentType<any>`.
|
- `Page` is of type `React.ComponentType<any>`.
|
||||||
It offers flexibility in defining the appearance and behavior of your page.
|
It offers flexibility in defining the appearance and behavior of your page.
|
||||||
|
|
||||||
`HelpPage` in the example above can be defined in `page.tsx`:
|
`HelpPage` in the example above can be defined in `page.tsx`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export class HelpPage extends React.Component<{ extension: LensRendererExtension }> {
|
export class HelpPage extends React.Component<{
|
||||||
|
extension: LensRendererExtension;
|
||||||
|
}> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Help yourself</p>
|
<p>Help yourself</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -328,11 +333,12 @@ This way, `HelpPage` can access all `HelpExtension` subclass data.
|
|||||||
This example code shows how to create a global page, but not how to make that page available to the Lens user.
|
This example code shows how to create a global page, but not how to make that page available to the Lens user.
|
||||||
Global pages are typically made available in the following ways:
|
Global pages are typically made available in the following ways:
|
||||||
|
|
||||||
* To add global pages to the top menu bar, see [`appMenus`](../main-extension#appmenus) in the Main Extension guide.
|
- To add global pages to the top menu bar, see [`appMenus`](../main-extension#appmenus) in the Main Extension guide.
|
||||||
* To add global pages as an interactive element in the blue status bar along the bottom of the Lens UI, see [`statusBarItems`](#statusbaritems).
|
- To add global pages as an interactive element in the blue status bar along the bottom of the Lens UI, see [`statusBarItems`](#statusbaritems).
|
||||||
* To add global pages to the Welcome Page, see [`welcomeMenus`](#welcomemenus).
|
- To add global pages to the Welcome Page, see [`welcomeMenus`](#welcomemenus).
|
||||||
|
|
||||||
### `welcomeMenus`
|
### `welcomeMenus`
|
||||||
|
|
||||||
### `appPreferences`
|
### `appPreferences`
|
||||||
|
|
||||||
The Lens **Preferences** page is a built-in global page.
|
The Lens **Preferences** page is a built-in global page.
|
||||||
@ -342,22 +348,24 @@ The following example demonstrates adding a custom preference:
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { ExamplePreferenceHint, ExamplePreferenceInput } from "./src/example-preference";
|
import {
|
||||||
|
ExamplePreferenceHint,
|
||||||
|
ExamplePreferenceInput,
|
||||||
|
} from "./src/example-preference";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default class ExampleRendererExtension extends Renderer.LensExtension {
|
export default class ExampleRendererExtension extends Renderer.LensExtension {
|
||||||
|
|
||||||
@observable preference = { enabled: false };
|
@observable preference = { enabled: false };
|
||||||
|
|
||||||
appPreferences = [
|
appPreferences = [
|
||||||
{
|
{
|
||||||
title: "Example Preferences",
|
title: "Example Preferences",
|
||||||
components: {
|
components: {
|
||||||
Input: () => <ExamplePreferenceInput preference={this.preference}/>,
|
Input: () => <ExamplePreferenceInput preference={this.preference} />,
|
||||||
Hint: () => <ExamplePreferenceHint/>
|
Hint: () => <ExamplePreferenceHint />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -365,13 +373,13 @@ export default class ExampleRendererExtension extends Renderer.LensExtension {
|
|||||||
`appPreferences` is an array of objects that satisfies the `AppPreferenceRegistration` interface.
|
`appPreferences` is an array of objects that satisfies the `AppPreferenceRegistration` interface.
|
||||||
The properties of the `appPreferences` array objects are defined as follows:
|
The properties of the `appPreferences` array objects are defined as follows:
|
||||||
|
|
||||||
* `title` sets the heading text displayed on the Preferences page.
|
- `title` sets the heading text displayed on the Preferences page.
|
||||||
* `components` specifies two `React.Component` objects that define the interface for the preference.
|
- `components` specifies two `React.Component` objects that define the interface for the preference.
|
||||||
* `Input` specifies an interactive input element for the preference.
|
- `Input` specifies an interactive input element for the preference.
|
||||||
* `Hint` provides descriptive information for the preference, shown below the `Input` element.
|
- `Hint` provides descriptive information for the preference, shown below the `Input` element.
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Note that the input and the hint can be comprised of more sophisticated elements, according to the needs of the extension.
|
Note that the input and the hint can be comprised of more sophisticated elements, according to the needs of the extension.
|
||||||
|
|
||||||
`ExamplePreferenceInput` expects its React props to be set to an `ExamplePreferenceProps` instance.
|
`ExamplePreferenceInput` expects its React props to be set to an `ExamplePreferenceProps` instance.
|
||||||
This is how `ExampleRendererExtension` handles the state of the preference input.
|
This is how `ExampleRendererExtension` handles the state of the preference input.
|
||||||
@ -386,22 +394,19 @@ import { observer } from "mobx-react";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Component: {
|
Component: { Checkbox },
|
||||||
Checkbox,
|
|
||||||
},
|
|
||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
export class ExamplePreferenceProps {
|
export class ExamplePreferenceProps {
|
||||||
preference: {
|
preference: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ExamplePreferenceInput extends React.Component<ExamplePreferenceProps> {
|
export class ExamplePreferenceInput extends React.Component<ExamplePreferenceProps> {
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super({preference: { enabled: false}});
|
super({ preference: { enabled: false } });
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,7 +416,9 @@ export class ExamplePreferenceInput extends React.Component<ExamplePreferencePro
|
|||||||
<Checkbox
|
<Checkbox
|
||||||
label="I understand appPreferences"
|
label="I understand appPreferences"
|
||||||
value={preference.enabled}
|
value={preference.enabled}
|
||||||
onChange={v => { preference.enabled = v; }}
|
onChange={(v) => {
|
||||||
|
preference.enabled = v;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -419,18 +426,16 @@ export class ExamplePreferenceInput extends React.Component<ExamplePreferencePro
|
|||||||
|
|
||||||
export class ExamplePreferenceHint extends React.Component {
|
export class ExamplePreferenceHint extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <span>This is an example of an appPreference for extensions.</span>;
|
||||||
<span>This is an example of an appPreference for extensions.</span>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`ExamplePreferenceInput` implements a simple checkbox using Lens's `Renderer.Component.Checkbox` using the following properties:
|
`ExamplePreferenceInput` implements a simple checkbox using Lens's `Renderer.Component.Checkbox` using the following properties:
|
||||||
|
|
||||||
* `label` sets the text that displays next to the checkbox.
|
- `label` sets the text that displays next to the checkbox.
|
||||||
* `value` is initially set to `preference.enabled`.
|
- `value` is initially set to `preference.enabled`.
|
||||||
* `onChange` is a function that responds when the state of the checkbox changes.
|
- `onChange` is a function that responds when the state of the checkbox changes.
|
||||||
|
|
||||||
`ExamplePreferenceInput` is defined with the `ExamplePreferenceProps` React props.
|
`ExamplePreferenceInput` is defined with the `ExamplePreferenceProps` React props.
|
||||||
This is an object with the single `enabled` property.
|
This is an object with the single `enabled` property.
|
||||||
@ -461,18 +466,18 @@ The following example adds a `statusBarItems` definition and a `globalPages` def
|
|||||||
It configures the status bar item to navigate to the global page upon activation (normally a mouse click):
|
It configures the status bar item to navigate to the global page upon activation (normally a mouse click):
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from '@k8slens/extensions';
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { HelpIcon, HelpPage } from "./page"
|
import { HelpIcon, HelpPage } from "./page";
|
||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
export default class HelpExtension extends Renderer.LensExtension {
|
export default class HelpExtension extends Renderer.LensExtension {
|
||||||
globalPages = [
|
globalPages = [
|
||||||
{
|
{
|
||||||
id: "help",
|
id: "help",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <HelpPage extension={this}/>,
|
Page: () => <HelpPage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
statusBarItems = [
|
statusBarItems = [
|
||||||
@ -486,7 +491,7 @@ export default class HelpExtension extends Renderer.LensExtension {
|
|||||||
<HelpIcon />
|
<HelpIcon />
|
||||||
My Status Bar Item
|
My Status Bar Item
|
||||||
</div>
|
</div>
|
||||||
)
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -495,14 +500,14 @@ export default class HelpExtension extends Renderer.LensExtension {
|
|||||||
|
|
||||||
The properties of the `statusBarItems` array objects are defined as follows:
|
The properties of the `statusBarItems` array objects are defined as follows:
|
||||||
|
|
||||||
* `Item` specifies the `React.Component` that will be shown on the status bar.
|
- `Item` specifies the `React.Component` that will be shown on the status bar.
|
||||||
By default, items are added starting from the right side of the status bar.
|
By default, items are added starting from the right side of the status bar.
|
||||||
Due to limited space in the status bar, `Item` will typically specify only an icon or a short string of text.
|
Due to limited space in the status bar, `Item` will typically specify only an icon or a short string of text.
|
||||||
The example above reuses the `HelpIcon` from the [`globalPageMenus` guide](#globalpagemenus).
|
The example above reuses the `HelpIcon` from the [`globalPageMenus` guide](#globalpagemenus).
|
||||||
* `onClick` determines what the `statusBarItem` does when it is clicked.
|
- `onClick` determines what the `statusBarItem` does when it is clicked.
|
||||||
In the example, `onClick` is set to a function that calls the `LensRendererExtension` `navigate()` method.
|
In the example, `onClick` is set to a function that calls the `LensRendererExtension` `navigate()` method.
|
||||||
`navigate` takes the `id` of the associated global page as a parameter.
|
`navigate` takes the `id` of the associated global page as a parameter.
|
||||||
Thus, clicking the status bar item activates the associated global pages.
|
Thus, clicking the status bar item activates the associated global pages.
|
||||||
|
|
||||||
### `kubeObjectMenuItems`
|
### `kubeObjectMenuItems`
|
||||||
|
|
||||||
@ -518,9 +523,9 @@ They also appear on the title bar of the details page for specific resources:
|
|||||||
The following example shows how to add a `kubeObjectMenuItems` for namespace resources with an associated action:
|
The following example shows how to add a `kubeObjectMenuItems` for namespace resources with an associated action:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import React from "react"
|
import React from "react";
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { NamespaceMenuItem } from "./src/namespace-menu-item"
|
import { NamespaceMenuItem } from "./src/namespace-menu-item";
|
||||||
|
|
||||||
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
||||||
type Namespace = Renderer.K8sApi.Namespace;
|
type Namespace = Renderer.K8sApi.Namespace;
|
||||||
@ -531,23 +536,24 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
kind: "Namespace",
|
kind: "Namespace",
|
||||||
apiVersions: ["v1"],
|
apiVersions: ["v1"],
|
||||||
components: {
|
components: {
|
||||||
MenuItem: (props: KubeObjectMenuProps<Namespace>) => <NamespaceMenuItem {...props} />
|
MenuItem: (props: KubeObjectMenuProps<Namespace>) => (
|
||||||
}
|
<NamespaceMenuItem {...props} />
|
||||||
}
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`kubeObjectMenuItems` is an array of objects matching the `KubeObjectMenuRegistration` interface.
|
`kubeObjectMenuItems` is an array of objects matching the `KubeObjectMenuRegistration` interface.
|
||||||
The example above adds a menu item for namespaces in the cluster dashboard.
|
The example above adds a menu item for namespaces in the cluster dashboard.
|
||||||
The properties of the `kubeObjectMenuItems` array objects are defined as follows:
|
The properties of the `kubeObjectMenuItems` array objects are defined as follows:
|
||||||
|
|
||||||
* `kind` specifies the Kubernetes resource type the menu item will apply to.
|
- `kind` specifies the Kubernetes resource type the menu item will apply to.
|
||||||
* `apiVersion` specifies the Kubernetes API version number to use with the resource type.
|
- `apiVersion` specifies the Kubernetes API version number to use with the resource type.
|
||||||
* `components` defines the menu item's appearance and behavior.
|
- `components` defines the menu item's appearance and behavior.
|
||||||
* `MenuItem` provides a function that returns a `React.Component` given a set of menu item properties.
|
- `MenuItem` provides a function that returns a `React.Component` given a set of menu item properties.
|
||||||
In this example a `NamespaceMenuItem` object is returned.
|
In this example a `NamespaceMenuItem` object is returned.
|
||||||
|
|
||||||
`NamespaceMenuItem` is defined in `./src/namespace-menu-item.tsx`:
|
`NamespaceMenuItem` is defined in `./src/namespace-menu-item.tsx`:
|
||||||
|
|
||||||
@ -556,11 +562,7 @@ import React from "react";
|
|||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Component: {
|
Component: { terminalStore, MenuItem, Icon },
|
||||||
terminalStore,
|
|
||||||
MenuItem,
|
|
||||||
Icon,
|
|
||||||
},
|
|
||||||
Navigation,
|
Navigation,
|
||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
@ -587,12 +589,15 @@ export function NamespaceMenuItem(props: KubeObjectMenuProps<Namespace>) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem onClick={getPods}>
|
<MenuItem onClick={getPods}>
|
||||||
<Icon material="speaker_group" interactive={toolbar} title="Get pods in terminal"/>
|
<Icon
|
||||||
|
material="speaker_group"
|
||||||
|
interactive={toolbar}
|
||||||
|
title="Get pods in terminal"
|
||||||
|
/>
|
||||||
<span className="title">Get Pods</span>
|
<span className="title">Get Pods</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`NamespaceMenuItem` returns a `Renderer.Component.MenuItem` which defines the menu item's appearance and its behavior when activated via the `onClick` property.
|
`NamespaceMenuItem` returns a `Renderer.Component.MenuItem` which defines the menu item's appearance and its behavior when activated via the `onClick` property.
|
||||||
@ -629,9 +634,11 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
apiVersions: ["v1"],
|
apiVersions: ["v1"],
|
||||||
priority: 10,
|
priority: 10,
|
||||||
components: {
|
components: {
|
||||||
Details: (props: KubeObjectDetailsProps<Namespace>) => <NamespaceDetailsItem {...props} />
|
Details: (props: KubeObjectDetailsProps<Namespace>) => (
|
||||||
}
|
<NamespaceDetailsItem {...props} />
|
||||||
}
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -640,15 +647,15 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
This example above adds a detail item for namespaces in the cluster dashboard.
|
This example above adds a detail item for namespaces in the cluster dashboard.
|
||||||
The properties of the `kubeObjectDetailItems` array objects are defined as follows:
|
The properties of the `kubeObjectDetailItems` array objects are defined as follows:
|
||||||
|
|
||||||
* `kind` specifies the Kubernetes resource type the detail item will apply to.
|
- `kind` specifies the Kubernetes resource type the detail item will apply to.
|
||||||
* `apiVersion` specifies the Kubernetes API version number to use with the resource type.
|
- `apiVersion` specifies the Kubernetes API version number to use with the resource type.
|
||||||
* `components` defines the detail item's appearance and behavior.
|
- `components` defines the detail item's appearance and behavior.
|
||||||
* `Details` provides a function that returns a `React.Component` given a set of detail item properties.
|
- `Details` provides a function that returns a `React.Component` given a set of detail item properties.
|
||||||
In this example a `NamespaceDetailsItem` object is returned.
|
In this example a `NamespaceDetailsItem` object is returned.
|
||||||
|
|
||||||
`NamespaceDetailsItem` is defined in `./src/namespace-details-item.tsx`:
|
`NamespaceDetailsItem` is defined in `./src/namespace-details-item.tsx`:
|
||||||
|
|
||||||
``` typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { PodsDetailsList } from "./pods-details-list";
|
import { PodsDetailsList } from "./pods-details-list";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@ -656,12 +663,8 @@ import { observable } from "mobx";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
K8sApi: {
|
K8sApi: { podsApi },
|
||||||
podsApi,
|
Component: { DrawerTitle },
|
||||||
},
|
|
||||||
Component: {
|
|
||||||
DrawerTitle,
|
|
||||||
},
|
|
||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
||||||
@ -669,7 +672,9 @@ type Namespace = Renderer.K8sApi.Namespace;
|
|||||||
type Pod = Renderer.K8sApi.Pod;
|
type Pod = Renderer.K8sApi.Pod;
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class NamespaceDetailsItem extends React.Component<KubeObjectDetailsProps<Namespace>> {
|
export class NamespaceDetailsItem extends React.Component<
|
||||||
|
KubeObjectDetailsProps<Namespace>
|
||||||
|
> {
|
||||||
@observable private pods: Pod[];
|
@observable private pods: Pod[];
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
@ -681,10 +686,10 @@ export class NamespaceDetailsItem extends React.Component<KubeObjectDetailsProps
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<DrawerTitle title="Pods" />
|
<DrawerTitle>Pods</DrawerTitle>
|
||||||
<PodsDetailsList pods={this.pods}/>
|
<PodsDetailsList pods={this.pods} />
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -709,17 +714,12 @@ Details are placed in drawers, and using `Renderer.Component.DrawerTitle` provid
|
|||||||
Multiple details in a drawer can be placed in `<Renderer.Component.DrawerItem>` elements for further separation, if desired.
|
Multiple details in a drawer can be placed in `<Renderer.Component.DrawerItem>` elements for further separation, if desired.
|
||||||
The rest of this example's details are defined in `PodsDetailsList`, found in `./pods-details-list.tsx`:
|
The rest of this example's details are defined in `PodsDetailsList`, found in `./pods-details-list.tsx`:
|
||||||
|
|
||||||
``` typescript
|
```typescript
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Component: {
|
Component: { TableHead, TableRow, TableCell, Table },
|
||||||
TableHead,
|
|
||||||
TableRow,
|
|
||||||
TableCell,
|
|
||||||
Table,
|
|
||||||
},
|
|
||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
type Pod = Renderer.K8sApi.Pod;
|
type Pod = Renderer.K8sApi.Pod;
|
||||||
@ -736,11 +736,11 @@ export class PodsDetailsList extends React.Component<PodsDetailsListProps> {
|
|||||||
<TableCell className="podAge">{pods[index].getAge()}</TableCell>
|
<TableCell className="podAge">{pods[index].getAge()}</TableCell>
|
||||||
<TableCell className="podStatus">{pods[index].getStatus()}</TableCell>
|
<TableCell className="podStatus">{pods[index].getStatus()}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { pods } = this.props
|
const { pods } = this.props;
|
||||||
|
|
||||||
if (!pods?.length) {
|
if (!pods?.length) {
|
||||||
return null;
|
return null;
|
||||||
@ -754,7 +754,7 @@ export class PodsDetailsList extends React.Component<PodsDetailsListProps> {
|
|||||||
<TableCell className="podAge">Age</TableCell>
|
<TableCell className="podAge">Age</TableCell>
|
||||||
<TableCell className="podStatus">Status</TableCell>
|
<TableCell className="podStatus">Status</TableCell>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
{ pods.map(this.getTableRow) }
|
{pods.map(this.getTableRow)}
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -393,7 +393,7 @@
|
|||||||
"ts-jest": "26.5.6",
|
"ts-jest": "26.5.6",
|
||||||
"ts-loader": "^9.2.6",
|
"ts-loader": "^9.2.6",
|
||||||
"ts-node": "^10.7.0",
|
"ts-node": "^10.7.0",
|
||||||
"type-fest": "^1.4.0",
|
"type-fest": "^2.12.0",
|
||||||
"typed-emitter": "^1.4.0",
|
"typed-emitter": "^1.4.0",
|
||||||
"typedoc": "0.22.10",
|
"typedoc": "0.22.10",
|
||||||
"typedoc-plugin-markdown": "^3.11.12",
|
"typedoc-plugin-markdown": "^3.11.12",
|
||||||
|
|||||||
@ -141,8 +141,11 @@ export function isMetricsEmpty(metrics: Record<string, IMetrics>) {
|
|||||||
return Object.values(metrics).every(metric => !metric?.data?.result?.length);
|
return Object.values(metrics).every(metric => !metric?.data?.result?.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getItemMetrics(metrics: Record<string, IMetrics>, itemName: string): Record<string, IMetrics> | void {
|
export function getItemMetrics(metrics: Record<string, IMetrics>, itemName: string): Record<string, IMetrics> | undefined {
|
||||||
if (!metrics) return;
|
if (!metrics) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const itemMetrics = { ...metrics };
|
const itemMetrics = { ...metrics };
|
||||||
|
|
||||||
for (const metric in metrics) {
|
for (const metric in metrics) {
|
||||||
|
|||||||
@ -31,17 +31,25 @@ export interface IPvcMetrics<T = IMetrics> {
|
|||||||
diskCapacity: T;
|
diskCapacity: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PersistentVolumeClaim {
|
export interface PersistentVolumeClaimSpec {
|
||||||
spec: {
|
accessModes: string[];
|
||||||
accessModes: string[];
|
selector: LabelSelector;
|
||||||
storageClassName: string;
|
resources: {
|
||||||
selector: LabelSelector;
|
requests?: Record<string, string>;
|
||||||
resources: {
|
limits?: Record<string, string>;
|
||||||
requests: {
|
|
||||||
storage: string; // 8Gi
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
volumeName?: string;
|
||||||
|
storageClassName?: string;
|
||||||
|
volumeMode?: string;
|
||||||
|
dataSource?: {
|
||||||
|
apiGroup: string;
|
||||||
|
kind: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PersistentVolumeClaim {
|
||||||
|
spec: PersistentVolumeClaimSpec;
|
||||||
status: {
|
status: {
|
||||||
phase: string; // Pending
|
phase: string; // Pending
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,6 +9,10 @@ import { IMetrics, metricsApi } from "./metrics.api";
|
|||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
import type { RequireExactlyOne } from "type-fest";
|
||||||
|
import type { KubeObjectMetadata, LocalObjectReference } from "../kube-object";
|
||||||
|
import type { SecretReference } from "./secret.api";
|
||||||
|
import type { PersistentVolumeClaimSpec } from "./persistent-volume-claims.api";
|
||||||
|
|
||||||
export class PodsApi extends KubeApi<Pod> {
|
export class PodsApi extends KubeApi<Pod> {
|
||||||
getLogs = async (params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise<string> => {
|
getLogs = async (params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise<string> => {
|
||||||
@ -112,12 +116,8 @@ export interface IPodContainer extends Partial<Record<PodContainerProbe, IContai
|
|||||||
};
|
};
|
||||||
}[];
|
}[];
|
||||||
envFrom?: {
|
envFrom?: {
|
||||||
configMapRef?: {
|
configMapRef?: LocalObjectReference;
|
||||||
name: string;
|
secretRef?: LocalObjectReference;
|
||||||
};
|
|
||||||
secretRef?: {
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
}[];
|
}[];
|
||||||
volumeMounts?: {
|
volumeMounts?: {
|
||||||
name: string;
|
name: string;
|
||||||
@ -195,6 +195,444 @@ export interface IPodContainerStatus {
|
|||||||
started?: boolean;
|
started?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AwsElasticBlockStoreSource {
|
||||||
|
volumeID: string;
|
||||||
|
fsType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AzureDiskSource {
|
||||||
|
/**
|
||||||
|
* The name of the VHD blob object OR the name of an Azure managed data disk if `kind` is `"Managed"`.
|
||||||
|
*/
|
||||||
|
diskName: string;
|
||||||
|
/**
|
||||||
|
* The URI of the vhd blob object OR the `resourceID` of an Azure managed data disk if `kind` is `"Managed"`.
|
||||||
|
*/
|
||||||
|
diskURI: string;
|
||||||
|
/**
|
||||||
|
* Kind of disk
|
||||||
|
* @default "Shared"
|
||||||
|
*/
|
||||||
|
kind?: "Shared" | "Dedicated" | "Managed";
|
||||||
|
/**
|
||||||
|
* Disk caching mode.
|
||||||
|
* @default "None"
|
||||||
|
*/
|
||||||
|
cachingMode?: "None" | "ReadOnly" | "ReadWrite";
|
||||||
|
/**
|
||||||
|
* The filesystem type to mount.
|
||||||
|
* @default "ext4"
|
||||||
|
*/
|
||||||
|
fsType?: string;
|
||||||
|
/**
|
||||||
|
* Whether the filesystem is used as readOnly.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
readonly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AzureFileSource {
|
||||||
|
/**
|
||||||
|
* The name of the secret that contains both Azure storage account name and key.
|
||||||
|
*/
|
||||||
|
secretName: string;
|
||||||
|
/**
|
||||||
|
* The share name to be used.
|
||||||
|
*/
|
||||||
|
shareName: string;
|
||||||
|
/**
|
||||||
|
* In case the secret is stored in a different namespace.
|
||||||
|
* @default "default"
|
||||||
|
*/
|
||||||
|
secretNamespace?: string;
|
||||||
|
/**
|
||||||
|
* Whether the filesystem is used as readOnly.
|
||||||
|
*/
|
||||||
|
readOnly: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CephfsSource {
|
||||||
|
/**
|
||||||
|
* List of Ceph monitors
|
||||||
|
*/
|
||||||
|
monitors: string[];
|
||||||
|
/**
|
||||||
|
* Used as the mounted root, rather than the full Ceph tree.
|
||||||
|
* @default "/"
|
||||||
|
*/
|
||||||
|
path?: string;
|
||||||
|
/**
|
||||||
|
* The RADOS user name.
|
||||||
|
* @default "admin"
|
||||||
|
*/
|
||||||
|
user?: string;
|
||||||
|
/**
|
||||||
|
* The path to the keyring file.
|
||||||
|
* @default "/etc/ceph/user.secret"
|
||||||
|
*/
|
||||||
|
secretFile?: string;
|
||||||
|
/**
|
||||||
|
* Reference to Ceph authentication secrets. If provided, then the secret overrides `secretFile`
|
||||||
|
*/
|
||||||
|
secretRef?: SecretReference;
|
||||||
|
/**
|
||||||
|
* Whether the filesystem is used as readOnly.
|
||||||
|
*/
|
||||||
|
readOnly: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CinderSource {
|
||||||
|
volumeID: string;
|
||||||
|
fsType: string;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
readOnly?: boolean;
|
||||||
|
secretRef?: SecretReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConfigMapSource {
|
||||||
|
name: string;
|
||||||
|
items: {
|
||||||
|
key: string;
|
||||||
|
path: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DownwardApiSource {
|
||||||
|
items: {
|
||||||
|
path: string;
|
||||||
|
fieldRef: {
|
||||||
|
fieldPath: string;
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EphemeralSource {
|
||||||
|
volumeClaimTemplate: {
|
||||||
|
/**
|
||||||
|
* All the rest of the fields are ignored and rejected during validation
|
||||||
|
*/
|
||||||
|
metadata?: Pick<KubeObjectMetadata, "labels" | "annotations">;
|
||||||
|
spec: PersistentVolumeClaimSpec;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EmptyDirSource {
|
||||||
|
medium?: string;
|
||||||
|
sizeLimit?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FiberChannelSource {
|
||||||
|
/**
|
||||||
|
* A list of World Wide Names
|
||||||
|
*/
|
||||||
|
targetWWNs: string[];
|
||||||
|
/**
|
||||||
|
* Logical Unit number
|
||||||
|
*/
|
||||||
|
lun: number;
|
||||||
|
/**
|
||||||
|
* The type of filesystem
|
||||||
|
* @default "ext4"
|
||||||
|
*/
|
||||||
|
fsType?: string;
|
||||||
|
readOnly: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FlockerSource {
|
||||||
|
datasetName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FlexVolumeSource {
|
||||||
|
driver: string;
|
||||||
|
fsType?: string;
|
||||||
|
secretRef?: LocalObjectReference;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
readOnly?: boolean;
|
||||||
|
options?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GcePersistentDiskSource {
|
||||||
|
pdName: string;
|
||||||
|
fsType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GitRepoSource {
|
||||||
|
repository: string;
|
||||||
|
revision: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GlusterFsSource {
|
||||||
|
/**
|
||||||
|
* The name of the Endpoints object that represents a Gluster cluster configuration.
|
||||||
|
*/
|
||||||
|
endpoints: string;
|
||||||
|
/**
|
||||||
|
* The Glusterfs volume name.
|
||||||
|
*/
|
||||||
|
path: string;
|
||||||
|
/**
|
||||||
|
* The boolean that sets the mountpoint readOnly or readWrite.
|
||||||
|
*/
|
||||||
|
readOnly: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HostPathSource {
|
||||||
|
path: string;
|
||||||
|
/**
|
||||||
|
* Determines the sorts of checks that will be done
|
||||||
|
* @default ""
|
||||||
|
*/
|
||||||
|
type?: "" | "DirectoryOrCreate" | "Directory" | "FileOrCreate" | "File" | "Socket" | "CharDevice" | "BlockDevice";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IScsiSource {
|
||||||
|
targetPortal: string;
|
||||||
|
iqn: string;
|
||||||
|
lun: number;
|
||||||
|
fsType: string;
|
||||||
|
readOnly: boolean;
|
||||||
|
chapAuthDiscovery?: boolean;
|
||||||
|
chapAuthSession?: boolean;
|
||||||
|
secretRef?: SecretReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LocalSource {
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NetworkFsSource {
|
||||||
|
server: string;
|
||||||
|
path: string;
|
||||||
|
readOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PersistentVolumeClaimSource {
|
||||||
|
claimName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PhotonPersistentDiskSource {
|
||||||
|
pdID: string;
|
||||||
|
/**
|
||||||
|
* @default "ext4"
|
||||||
|
*/
|
||||||
|
fsType?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PortworxVolumeSource {
|
||||||
|
volumeID: string;
|
||||||
|
fsType?: string;
|
||||||
|
readOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProjectedSource {
|
||||||
|
sources: {
|
||||||
|
secret?: {
|
||||||
|
name: string;
|
||||||
|
items?: {
|
||||||
|
key: string;
|
||||||
|
path: string;
|
||||||
|
mode?: number;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
downwardAPI?: {
|
||||||
|
items?: {
|
||||||
|
path: string;
|
||||||
|
fieldRef?: {
|
||||||
|
fieldPath: string;
|
||||||
|
apiVersion?: string;
|
||||||
|
};
|
||||||
|
resourceFieldRef?: {
|
||||||
|
resource: string;
|
||||||
|
containerName?: string;
|
||||||
|
};
|
||||||
|
mode?: number;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
configMap?: {
|
||||||
|
name: string;
|
||||||
|
items?: {
|
||||||
|
key: string;
|
||||||
|
path: string;
|
||||||
|
mode?: number;
|
||||||
|
}[];
|
||||||
|
optional?: boolean;
|
||||||
|
};
|
||||||
|
serviceAccountToken?: {
|
||||||
|
audience?: string;
|
||||||
|
expirationSeconds?: number;
|
||||||
|
path: string;
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
defaultMode: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QuobyteSource {
|
||||||
|
registry: string;
|
||||||
|
volume: string;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
readOnly?: boolean;
|
||||||
|
/**
|
||||||
|
* @default "serivceaccount"
|
||||||
|
*/
|
||||||
|
user?: string;
|
||||||
|
group?: string;
|
||||||
|
tenant?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RadosBlockDeviceSource {
|
||||||
|
monitors: string[];
|
||||||
|
image: string;
|
||||||
|
/**
|
||||||
|
* @default "ext4"
|
||||||
|
*/
|
||||||
|
fsType?: string;
|
||||||
|
/**
|
||||||
|
* @default "rbd"
|
||||||
|
*/
|
||||||
|
pool?: string;
|
||||||
|
/**
|
||||||
|
* @default "admin"
|
||||||
|
*/
|
||||||
|
user?: string;
|
||||||
|
/**
|
||||||
|
* @default "/etc/ceph/keyring"
|
||||||
|
*/
|
||||||
|
keyring?: string;
|
||||||
|
secretRef?: SecretReference;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
readOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScaleIoSource {
|
||||||
|
gateway: string;
|
||||||
|
system: string;
|
||||||
|
secretRef?: LocalObjectReference;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
sslEnabled?: boolean;
|
||||||
|
protectionDomain?: string;
|
||||||
|
storagePool?: string;
|
||||||
|
/**
|
||||||
|
* @default "ThinProvisioned"
|
||||||
|
*/
|
||||||
|
storageMode?: "ThickProvisioned" | "ThinProvisioned";
|
||||||
|
volumeName: string;
|
||||||
|
/**
|
||||||
|
* @default "xfs"
|
||||||
|
*/
|
||||||
|
fsType?: string;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
readOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SecretSource {
|
||||||
|
secretName: string;
|
||||||
|
items?: {
|
||||||
|
key: string;
|
||||||
|
path: string;
|
||||||
|
mode?: number;
|
||||||
|
}[];
|
||||||
|
defaultMode?: number;
|
||||||
|
optional?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StorageOsSource {
|
||||||
|
volumeName: string;
|
||||||
|
/**
|
||||||
|
* @default Pod.metadata.namespace
|
||||||
|
*/
|
||||||
|
volumeNamespace?: string;
|
||||||
|
/**
|
||||||
|
* @default "ext4"
|
||||||
|
*/
|
||||||
|
fsType?: string;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
readOnly?: boolean;
|
||||||
|
secretRef?: LocalObjectReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VsphereVolumeSource {
|
||||||
|
volumePath: string;
|
||||||
|
/**
|
||||||
|
* @default "ext4"
|
||||||
|
*/
|
||||||
|
fsType?: string;
|
||||||
|
storagePolicyName?: string;
|
||||||
|
storagePolicyID?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContainerStorageInterfaceSource {
|
||||||
|
driver: string;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
readOnly?: boolean;
|
||||||
|
/**
|
||||||
|
* @default "ext4"
|
||||||
|
*/
|
||||||
|
fsType?: string;
|
||||||
|
volumeAttributes?: Record<string, string>;
|
||||||
|
controllerPublishSecretRef?: SecretReference;
|
||||||
|
nodeStageSecretRef?: SecretReference;
|
||||||
|
nodePublishSecretRef?: SecretReference;
|
||||||
|
controllerExpandSecretRef?: SecretReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PodVolumeVariants {
|
||||||
|
awsElasticBlockStore: AwsElasticBlockStoreSource;
|
||||||
|
azureDisk: AzureDiskSource;
|
||||||
|
azureFile: AzureFileSource;
|
||||||
|
cephfs: CephfsSource;
|
||||||
|
cinder: CinderSource;
|
||||||
|
configMap: ConfigMapSource;
|
||||||
|
csi: ContainerStorageInterfaceSource;
|
||||||
|
downwardAPI: DownwardApiSource;
|
||||||
|
emptyDir: EmptyDirSource;
|
||||||
|
ephemeral: EphemeralSource;
|
||||||
|
fc: FiberChannelSource;
|
||||||
|
flexVolume: FlexVolumeSource;
|
||||||
|
flocker: FlockerSource;
|
||||||
|
gcePersistentDisk: GcePersistentDiskSource;
|
||||||
|
gitRepo: GitRepoSource;
|
||||||
|
glusterfs: GlusterFsSource;
|
||||||
|
hostPath: HostPathSource;
|
||||||
|
iscsi: IScsiSource;
|
||||||
|
local: LocalSource;
|
||||||
|
nfs: NetworkFsSource;
|
||||||
|
persistentVolumeClaim: PersistentVolumeClaimSource;
|
||||||
|
photonPersistentDisk: PhotonPersistentDiskSource;
|
||||||
|
portworxVolume: PortworxVolumeSource;
|
||||||
|
projected: ProjectedSource;
|
||||||
|
quobyte: QuobyteSource;
|
||||||
|
rbd: RadosBlockDeviceSource;
|
||||||
|
scaleIO: ScaleIoSource;
|
||||||
|
secret: SecretSource;
|
||||||
|
storageos: StorageOsSource;
|
||||||
|
vsphereVolume: VsphereVolumeSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The valid kinds of volume
|
||||||
|
*/
|
||||||
|
export type PodVolumeKind = keyof PodVolumeVariants;
|
||||||
|
|
||||||
|
export type PodVolume = RequireExactlyOne<PodVolumeVariants> & {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
export class Pod extends WorkloadKubeObject {
|
export class Pod extends WorkloadKubeObject {
|
||||||
static kind = "Pod";
|
static kind = "Pod";
|
||||||
static namespaced = true;
|
static namespaced = true;
|
||||||
@ -206,23 +644,7 @@ export class Pod extends WorkloadKubeObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare spec?: {
|
declare spec?: {
|
||||||
volumes?: {
|
volumes?: PodVolume[];
|
||||||
name: string;
|
|
||||||
persistentVolumeClaim: {
|
|
||||||
claimName: string;
|
|
||||||
};
|
|
||||||
emptyDir: {
|
|
||||||
medium?: string;
|
|
||||||
sizeLimit?: string;
|
|
||||||
};
|
|
||||||
configMap: {
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
secret: {
|
|
||||||
secretName: string;
|
|
||||||
defaultMode: number;
|
|
||||||
};
|
|
||||||
}[];
|
|
||||||
initContainers: IPodContainer[];
|
initContainers: IPodContainer[];
|
||||||
containers: IPodContainer[];
|
containers: IPodContainer[];
|
||||||
restartPolicy?: string;
|
restartPolicy?: string;
|
||||||
@ -239,9 +661,7 @@ export class Pod extends WorkloadKubeObject {
|
|||||||
[selector: string]: string;
|
[selector: string]: string;
|
||||||
};
|
};
|
||||||
securityContext?: {};
|
securityContext?: {};
|
||||||
imagePullSecrets?: {
|
imagePullSecrets?: LocalObjectReference[];
|
||||||
name: string;
|
|
||||||
}[];
|
|
||||||
hostNetwork?: boolean;
|
hostNetwork?: boolean;
|
||||||
hostPID?: boolean;
|
hostPID?: boolean;
|
||||||
hostIPC?: boolean;
|
hostIPC?: boolean;
|
||||||
|
|||||||
@ -25,6 +25,11 @@ export interface ISecretRef {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SecretReference {
|
||||||
|
name: string;
|
||||||
|
namespace?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface SecretData extends KubeJsonApiData {
|
export interface SecretData extends KubeJsonApiData {
|
||||||
type: SecretType;
|
type: SecretType;
|
||||||
data?: Record<string, string>;
|
data?: Record<string, string>;
|
||||||
|
|||||||
@ -21,6 +21,13 @@ export type KubeObjectConstructor<K extends KubeObject> = (new (data: KubeJsonAp
|
|||||||
apiBase?: string;
|
apiBase?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to an object in the same namespace
|
||||||
|
*/
|
||||||
|
export interface LocalObjectReference {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface KubeObjectMetadata {
|
export interface KubeObjectMetadata {
|
||||||
uid: string;
|
uid: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@ -134,7 +134,7 @@ export class HpaDetails extends React.Component<HpaDetailsProps> {
|
|||||||
})}
|
})}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerTitle title="Metrics"/>
|
<DrawerTitle>Metrics</DrawerTitle>
|
||||||
<div className="metrics">
|
<div className="metrics">
|
||||||
{this.renderMetrics()}
|
{this.renderMetrics()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -85,7 +85,7 @@ export class ConfigMapDetails extends React.Component<ConfigMapDetailsProps> {
|
|||||||
{
|
{
|
||||||
data.length > 0 && (
|
data.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Data"/>
|
<DrawerTitle>Data</DrawerTitle>
|
||||||
{
|
{
|
||||||
data.map(([name, value]) => (
|
data.map(([name, value]) => (
|
||||||
<div key={name} className="data">
|
<div key={name} className="data">
|
||||||
|
|||||||
@ -82,7 +82,7 @@ export class ResourceQuotaDetails extends React.Component<ResourceQuotaDetailsPr
|
|||||||
|
|
||||||
{quota.getScopeSelector().length > 0 && (
|
{quota.getScopeSelector().length > 0 && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Scope Selector"/>
|
<DrawerTitle>Scope Selector</DrawerTitle>
|
||||||
<Table className="paths">
|
<Table className="paths">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Operator</TableCell>
|
<TableCell>Operator</TableCell>
|
||||||
|
|||||||
@ -116,7 +116,7 @@ export class SecretDetails extends React.Component<SecretDetailsProps> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Data" />
|
<DrawerTitle>Data</DrawerTitle>
|
||||||
{secrets.map(this.renderSecret)}
|
{secrets.map(this.renderSecret)}
|
||||||
<Button
|
<Button
|
||||||
primary
|
primary
|
||||||
|
|||||||
@ -92,7 +92,7 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerTitle title="Names"/>
|
<DrawerTitle>Names</DrawerTitle>
|
||||||
<Table selectable className="names box grow">
|
<Table selectable className="names box grow">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>plural</TableCell>
|
<TableCell>plural</TableCell>
|
||||||
@ -109,7 +109,7 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
|||||||
</Table>
|
</Table>
|
||||||
{printerColumns.length > 0 &&
|
{printerColumns.length > 0 &&
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Additional Printer Columns"/>
|
<DrawerTitle>Additional Printer Columns</DrawerTitle>
|
||||||
<Table selectable className="printer-columns box grow">
|
<Table selectable className="printer-columns box grow">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell className="name">Name</TableCell>
|
<TableCell className="name">Name</TableCell>
|
||||||
@ -136,7 +136,7 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
|||||||
}
|
}
|
||||||
{validation &&
|
{validation &&
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Validation"/>
|
<DrawerTitle>Validation</DrawerTitle>
|
||||||
<MonacoEditor
|
<MonacoEditor
|
||||||
readOnly
|
readOnly
|
||||||
value={validation}
|
value={validation}
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export class EventDetails extends React.Component<EventDetailsProps> {
|
|||||||
<span className={kebabCase(type)}>{type}</span>
|
<span className={kebabCase(type)}>{type}</span>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerTitle title="Involved object"/>
|
<DrawerTitle>Involved object</DrawerTitle>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Name</TableCell>
|
<TableCell>Name</TableCell>
|
||||||
|
|||||||
@ -113,7 +113,7 @@ class NonInjectedReleaseDetails extends Component<ReleaseDetailsProps & Dependen
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="values">
|
<div className="values">
|
||||||
<DrawerTitle title="Values" />
|
<DrawerTitle>Values</DrawerTitle>
|
||||||
<div className="flex column gaps">
|
<div className="flex column gaps">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="User-supplied values only"
|
label="User-supplied values only"
|
||||||
@ -238,9 +238,9 @@ class NonInjectedReleaseDetails extends Component<ReleaseDetailsProps & Dependen
|
|||||||
/>
|
/>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
{this.renderValues()}
|
{this.renderValues()}
|
||||||
<DrawerTitle title="Notes"/>
|
<DrawerTitle>Notes</DrawerTitle>
|
||||||
{this.renderNotes()}
|
{this.renderNotes()}
|
||||||
<DrawerTitle title="Resources"/>
|
<DrawerTitle>Resources</DrawerTitle>
|
||||||
{resources && this.renderResources(resources)}
|
{resources && this.renderResources(resources)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export class EndpointDetails extends React.Component<EndpointDetailsProps> {
|
|||||||
return (
|
return (
|
||||||
<div className="EndpointDetails">
|
<div className="EndpointDetails">
|
||||||
<KubeObjectMeta object={endpoint}/>
|
<KubeObjectMeta object={endpoint}/>
|
||||||
<DrawerTitle title="Subsets"/>
|
<DrawerTitle>Subsets</DrawerTitle>
|
||||||
{
|
{
|
||||||
endpoint.getEndpointSubsets().map((subset) => (
|
endpoint.getEndpointSubsets().map((subset) => (
|
||||||
<EndpointSubsetList key={subset.toString()} subset={subset} endpoint={endpoint} />
|
<EndpointSubsetList key={subset.toString()} subset={subset} endpoint={endpoint} />
|
||||||
|
|||||||
@ -160,10 +160,10 @@ export class IngressDetails extends React.Component<IngressDetailsProps> {
|
|||||||
{serviceName}:{servicePort}
|
{serviceName}:{servicePort}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
}
|
}
|
||||||
<DrawerTitle title="Rules"/>
|
<DrawerTitle>Rules</DrawerTitle>
|
||||||
{this.renderPaths(ingress)}
|
{this.renderPaths(ingress)}
|
||||||
|
|
||||||
<DrawerTitle title="Load-Balancer Ingress Points"/>
|
<DrawerTitle>Load-Balancer Ingress Points</DrawerTitle>
|
||||||
{this.renderIngressPoints(ingressPoints)}
|
{this.renderIngressPoints(ingressPoints)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -170,7 +170,7 @@ export class NetworkPolicyDetails extends React.Component<NetworkPolicyDetailsPr
|
|||||||
|
|
||||||
{ingress && (
|
{ingress && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Ingress"/>
|
<DrawerTitle>Ingress</DrawerTitle>
|
||||||
{ingress.map((ingress, i) => (
|
{ingress.map((ingress, i) => (
|
||||||
<div key={i} data-testid={`ingress-${i}`}>
|
<div key={i} data-testid={`ingress-${i}`}>
|
||||||
{this.renderNetworkPolicyPorts(ingress.ports)}
|
{this.renderNetworkPolicyPorts(ingress.ports)}
|
||||||
@ -182,7 +182,7 @@ export class NetworkPolicyDetails extends React.Component<NetworkPolicyDetailsPr
|
|||||||
|
|
||||||
{egress && (
|
{egress && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Egress"/>
|
<DrawerTitle>Egress</DrawerTitle>
|
||||||
{egress.map((egress, i) => (
|
{egress.map((egress, i) => (
|
||||||
<div key={i} data-testid={`egress-${i}`}>
|
<div key={i} data-testid={`egress-${i}`}>
|
||||||
{this.renderNetworkPolicyPorts(egress.ports)}
|
{this.renderNetworkPolicyPorts(egress.ports)}
|
||||||
|
|||||||
@ -86,7 +86,7 @@ class NonInjectedServiceDetails extends React.Component<ServiceDetailsProps & De
|
|||||||
{spec.sessionAffinity}
|
{spec.sessionAffinity}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerTitle title="Connection"/>
|
<DrawerTitle>Connection</DrawerTitle>
|
||||||
|
|
||||||
<DrawerItem name="Cluster IP">
|
<DrawerItem name="Cluster IP">
|
||||||
{spec.clusterIP}
|
{spec.clusterIP}
|
||||||
@ -129,7 +129,7 @@ class NonInjectedServiceDetails extends React.Component<ServiceDetailsProps & De
|
|||||||
{spec.loadBalancerIP}
|
{spec.loadBalancerIP}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
)}
|
)}
|
||||||
<DrawerTitle title="Endpoint"/>
|
<DrawerTitle>Endpoint</DrawerTitle>
|
||||||
|
|
||||||
<ServiceDetailsEndpoint endpoint={endpoint}/>
|
<ServiceDetailsEndpoint endpoint={endpoint}/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -169,9 +169,9 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
|
|||||||
}
|
}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
}
|
}
|
||||||
<DrawerTitle title="Capacity"/>
|
<DrawerTitle>Capacity</DrawerTitle>
|
||||||
<NodeDetailsResources node={node} type={"capacity"}/>
|
<NodeDetailsResources node={node} type={"capacity"}/>
|
||||||
<DrawerTitle title="Allocatable"/>
|
<DrawerTitle>Allocatable</DrawerTitle>
|
||||||
<NodeDetailsResources node={node} type={"allocatable"}/>
|
<NodeDetailsResources node={node} type={"allocatable"}/>
|
||||||
<PodDetailsList
|
<PodDetailsList
|
||||||
pods={childPods}
|
pods={childPods}
|
||||||
|
|||||||
@ -28,26 +28,23 @@ interface RuleGroup {
|
|||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyDetailsProps> {
|
export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyDetailsProps> {
|
||||||
renderRuleGroup( title: React.ReactNode, group: RuleGroup) {
|
renderRuleGroup = (title: React.ReactNode, { rule, ranges }: RuleGroup) => (
|
||||||
if (!group) return null;
|
<>
|
||||||
const { rule, ranges } = group;
|
<DrawerTitle>{title}</DrawerTitle>
|
||||||
|
<DrawerItem name="Rule">
|
||||||
return (
|
{rule}
|
||||||
<>
|
</DrawerItem>
|
||||||
<DrawerTitle title={title}/>
|
{ranges && (
|
||||||
<DrawerItem name="Rule">
|
<DrawerItem name="Ranges (Min-Max)" labelsOnly>
|
||||||
{rule}
|
{ranges.map(({ min, max }, index) => (
|
||||||
|
<Badge
|
||||||
|
key={index}
|
||||||
|
label={`${min} - ${max}`} />
|
||||||
|
))}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
{ranges && (
|
)}
|
||||||
<DrawerItem name="Ranges (Min-Max)" labelsOnly>
|
</>
|
||||||
{ranges.map(({ min, max }, index) => {
|
);
|
||||||
return <Badge key={index} label={`${min} - ${max}`}/>;
|
|
||||||
})}
|
|
||||||
</DrawerItem>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { object: psp } = this.props;
|
const { object: psp } = this.props;
|
||||||
@ -161,7 +158,7 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
|||||||
|
|
||||||
{allowedHostPaths && (
|
{allowedHostPaths && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Allowed Host Paths"/>
|
<DrawerTitle>Allowed Host Paths</DrawerTitle>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Path Prefix</TableCell>
|
<TableCell>Path Prefix</TableCell>
|
||||||
@ -179,14 +176,14 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{this.renderRuleGroup("Fs Group", fsGroup)}
|
{fsGroup && this.renderRuleGroup("Fs Group", fsGroup)}
|
||||||
{this.renderRuleGroup("Run As Group", runAsGroup)}
|
{runAsGroup && this.renderRuleGroup("Run As Group", runAsGroup)}
|
||||||
{this.renderRuleGroup("Run As User", runAsUser)}
|
{runAsUser && this.renderRuleGroup("Run As User", runAsUser)}
|
||||||
{this.renderRuleGroup("Supplemental Groups", supplementalGroups)}
|
{supplementalGroups && this.renderRuleGroup("Supplemental Groups", supplementalGroups)}
|
||||||
|
|
||||||
{runtimeClass && (
|
{runtimeClass && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Runtime Class"/>
|
<DrawerTitle>Runtime Class</DrawerTitle>
|
||||||
<DrawerItem name="Allowed Runtime Class Names">
|
<DrawerItem name="Allowed Runtime Class Names">
|
||||||
{runtimeClass.allowedRuntimeClassNames?.join(", ") || "-"}
|
{runtimeClass.allowedRuntimeClassNames?.join(", ") || "-"}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
@ -198,7 +195,7 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
|||||||
|
|
||||||
{seLinux && (
|
{seLinux && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Se Linux"/>
|
<DrawerTitle>Se Linux</DrawerTitle>
|
||||||
<DrawerItem name="Rule">
|
<DrawerItem name="Rule">
|
||||||
{seLinux.rule}
|
{seLinux.rule}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class NonInjectedStorageClassDetails extends React.Component<StorageClassDetails
|
|||||||
)}
|
)}
|
||||||
{parameters && (
|
{parameters && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Parameters"/>
|
<DrawerTitle>Parameters</DrawerTitle>
|
||||||
{
|
{
|
||||||
Object.entries(parameters).map(([name, value]) => (
|
Object.entries(parameters).map(([name, value]) => (
|
||||||
<DrawerItem key={name + value} name={startCase(name)}>
|
<DrawerItem key={name + value} name={startCase(name)}>
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export class PersistentVolumeClaimDetails extends React.Component<PersistentVolu
|
|||||||
{volumeClaim.getStatus()}
|
{volumeClaim.getStatus()}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerTitle title="Selector"/>
|
<DrawerTitle>Selector</DrawerTitle>
|
||||||
|
|
||||||
<DrawerItem name="Match Labels" labelsOnly>
|
<DrawerItem name="Match Labels" labelsOnly>
|
||||||
{volumeClaim.getMatchLabels().map(label => <Badge key={label} label={label}/>)}
|
{volumeClaim.getMatchLabels().map(label => <Badge key={label} label={label}/>)}
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export class VolumeDetailsList extends React.Component<VolumeDetailsListProps> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="VolumeDetailsList flex column">
|
<div className="VolumeDetailsList flex column">
|
||||||
<DrawerTitle title="Persistent Volumes"/>
|
<DrawerTitle>Persistent Volumes</DrawerTitle>
|
||||||
<Table
|
<Table
|
||||||
tableId="storage_volume_details_list"
|
tableId="storage_volume_details_list"
|
||||||
items={persistentVolumes}
|
items={persistentVolumes}
|
||||||
|
|||||||
@ -65,7 +65,7 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
|||||||
|
|
||||||
{nfs && (
|
{nfs && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Network File System"/>
|
<DrawerTitle>Network File System</DrawerTitle>
|
||||||
{
|
{
|
||||||
Object.entries(nfs).map(([name, value]) => (
|
Object.entries(nfs).map(([name, value]) => (
|
||||||
<DrawerItem key={name} name={startCase(name)}>
|
<DrawerItem key={name} name={startCase(name)}>
|
||||||
@ -78,7 +78,7 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
|||||||
|
|
||||||
{flexVolume && (
|
{flexVolume && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="FlexVolume"/>
|
<DrawerTitle>FlexVolume</DrawerTitle>
|
||||||
<DrawerItem name="Driver">
|
<DrawerItem name="Driver">
|
||||||
{flexVolume.driver}
|
{flexVolume.driver}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
@ -94,7 +94,7 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
|||||||
|
|
||||||
{claimRef && (
|
{claimRef && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Claim"/>
|
<DrawerTitle>Claim</DrawerTitle>
|
||||||
<DrawerItem name="Type">
|
<DrawerItem name="Type">
|
||||||
{claimRef.kind}
|
{claimRef.kind}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|||||||
@ -68,7 +68,7 @@ export class ClusterRoleBindingDetails extends React.Component<ClusterRoleBindin
|
|||||||
<div className="ClusterRoleBindingDetails">
|
<div className="ClusterRoleBindingDetails">
|
||||||
<KubeObjectMeta object={clusterRoleBinding} />
|
<KubeObjectMeta object={clusterRoleBinding} />
|
||||||
|
|
||||||
<DrawerTitle title="Reference" />
|
<DrawerTitle>Reference</DrawerTitle>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Kind</TableCell>
|
<TableCell>Kind</TableCell>
|
||||||
@ -82,7 +82,7 @@ export class ClusterRoleBindingDetails extends React.Component<ClusterRoleBindin
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
<DrawerTitle title="Bindings" />
|
<DrawerTitle>Bindings</DrawerTitle>
|
||||||
{subjects.length > 0 && (
|
{subjects.length > 0 && (
|
||||||
<Table selectable className="bindings box grow">
|
<Table selectable className="bindings box grow">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export class ClusterRoleDetails extends React.Component<ClusterRoleDetailsProps>
|
|||||||
<div className="ClusterRoleDetails">
|
<div className="ClusterRoleDetails">
|
||||||
<KubeObjectMeta object={clusterRole}/>
|
<KubeObjectMeta object={clusterRole}/>
|
||||||
|
|
||||||
<DrawerTitle title="Rules"/>
|
<DrawerTitle>Rules</DrawerTitle>
|
||||||
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
||||||
return (
|
return (
|
||||||
<div className="rule" key={index}>
|
<div className="rule" key={index}>
|
||||||
|
|||||||
@ -64,7 +64,7 @@ export class RoleBindingDetails extends React.Component<RoleBindingDetailsProps>
|
|||||||
<div className="RoleBindingDetails">
|
<div className="RoleBindingDetails">
|
||||||
<KubeObjectMeta object={roleBinding} />
|
<KubeObjectMeta object={roleBinding} />
|
||||||
|
|
||||||
<DrawerTitle title="Reference" />
|
<DrawerTitle>Reference</DrawerTitle>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Kind</TableCell>
|
<TableCell>Kind</TableCell>
|
||||||
@ -78,7 +78,7 @@ export class RoleBindingDetails extends React.Component<RoleBindingDetailsProps>
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
<DrawerTitle title="Bindings" />
|
<DrawerTitle>Bindings</DrawerTitle>
|
||||||
{subjects.length > 0 && (
|
{subjects.length > 0 && (
|
||||||
<Table selectable className="bindings box grow">
|
<Table selectable className="bindings box grow">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export class RoleDetails extends React.Component<RoleDetailsProps> {
|
|||||||
return (
|
return (
|
||||||
<div className="RoleDetails">
|
<div className="RoleDetails">
|
||||||
<KubeObjectMeta object={role}/>
|
<KubeObjectMeta object={role}/>
|
||||||
<DrawerTitle title="Rules"/>
|
<DrawerTitle>Rules</DrawerTitle>
|
||||||
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
||||||
return (
|
return (
|
||||||
<div className="rule" key={index}>
|
<div className="rule" key={index}>
|
||||||
|
|||||||
@ -143,7 +143,7 @@ export class ServiceAccountsDetails extends React.Component<ServiceAccountsDetai
|
|||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
}
|
}
|
||||||
|
|
||||||
<DrawerTitle title="Mountable secrets"/>
|
<DrawerTitle>Mountable secrets</DrawerTitle>
|
||||||
<div className="secrets">
|
<div className="secrets">
|
||||||
{this.renderSecrets()}
|
{this.renderSecrets()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -78,7 +78,7 @@ class NonInjectedCronJobDetails extends React.Component<CronJobDetailsProps & De
|
|||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
{childJobs.length > 0 &&
|
{childJobs.length > 0 &&
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Jobs"/>
|
<DrawerTitle>Jobs</DrawerTitle>
|
||||||
{childJobs.map((job: Job) => {
|
{childJobs.map((job: Job) => {
|
||||||
const selectors = job.getSelectors();
|
const selectors = job.getSelectors();
|
||||||
const condition = job.getCondition();
|
const condition = job.getCondition();
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export class DeploymentReplicaSets extends React.Component<DeploymentReplicaSets
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ReplicaSets flex column">
|
<div className="ReplicaSets flex column">
|
||||||
<DrawerTitle title="Deploy Revisions"/>
|
<DrawerTitle>Deploy Revisions</DrawerTitle>
|
||||||
<Table
|
<Table
|
||||||
selectable
|
selectable
|
||||||
tableId="deployment_replica_sets_view"
|
tableId="deployment_replica_sets_view"
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import type { PodVolumeVariants, Pod, SecretReference } from "../../../../../common/k8s-api/endpoints";
|
||||||
|
import type { KubeApi } from "../../../../../common/k8s-api/kube-api";
|
||||||
|
import type { LocalObjectReference, KubeObject } from "../../../../../common/k8s-api/kube-object";
|
||||||
|
import { DrawerItem } from "../../../drawer";
|
||||||
|
import { getDetailsUrl } from "../../../kube-detail-params";
|
||||||
|
|
||||||
|
export interface PodVolumeVariantSpecificProps<Kind extends keyof PodVolumeVariants> {
|
||||||
|
variant: PodVolumeVariants[Kind];
|
||||||
|
pod: Pod;
|
||||||
|
volumeName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VolumeVariantComponent<Kind extends keyof PodVolumeVariants> = React.FunctionComponent<PodVolumeVariantSpecificProps<Kind>>;
|
||||||
|
|
||||||
|
export interface LocalRefProps {
|
||||||
|
pod: Pod;
|
||||||
|
title: string;
|
||||||
|
kubeRef: LocalObjectReference | SecretReference | undefined;
|
||||||
|
api: KubeApi<KubeObject>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LocalRef = ({ pod, title, kubeRef: ref, api }: LocalRefProps) => {
|
||||||
|
if (!ref) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DrawerItem name={title}>
|
||||||
|
<Link to={getDetailsUrl(api.getUrl({ namespace: pod.getNs(), ...ref }))}>
|
||||||
|
{ref.name}
|
||||||
|
</Link>
|
||||||
|
</DrawerItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,291 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import type { Pod, PodVolume, PodVolumeKind } from "../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerItem } from "../../../drawer";
|
||||||
|
import { Icon } from "../../../icon";
|
||||||
|
import { AwsElasticBlockStore } from "./variants/aws-elastic-block-store";
|
||||||
|
import { AzureDisk } from "./variants/azure-disk";
|
||||||
|
import { AzureFile } from "./variants/azure-file";
|
||||||
|
import { CephFs } from "./variants/ceph-fs";
|
||||||
|
import { Cinder } from "./variants/cinder";
|
||||||
|
import { ConfigMap } from "./variants/config-map";
|
||||||
|
import { ContainerStorageInterface } from "./variants/container-storage-interface";
|
||||||
|
import { DownwardAPI } from "./variants/downward-api";
|
||||||
|
import { EmptyDir } from "./variants/empty-dir";
|
||||||
|
import { Ephemeral } from "./variants/ephemeral";
|
||||||
|
import { FiberChannel } from "./variants/fiber-channel";
|
||||||
|
import { FlexVolume } from "./variants/flex-volume";
|
||||||
|
import { Flocker } from "./variants/flocker";
|
||||||
|
import { GcePersistentDisk } from "./variants/gce-persistent-disk";
|
||||||
|
import { GitRepo } from "./variants/git-repo";
|
||||||
|
import { GlusterFs } from "./variants/gluster-fs";
|
||||||
|
import { HostPath } from "./variants/host-path";
|
||||||
|
import { IScsi } from "./variants/i-scsi";
|
||||||
|
import { Local } from "./variants/local";
|
||||||
|
import { NetworkFs } from "./variants/network-fs";
|
||||||
|
import { PersistentVolumeClaim } from "./variants/persistent-volume-claim";
|
||||||
|
import { PhotonPersistentDisk } from "./variants/photon-persistent-disk";
|
||||||
|
import { PortworxVolume } from "./variants/portworx-volume";
|
||||||
|
import { Projected } from "./variants/projected";
|
||||||
|
import { Quobyte } from "./variants/quobyte";
|
||||||
|
import { RadosBlockDevice } from "./variants/rados-block-device";
|
||||||
|
import { ScaleIo } from "./variants/scale-io";
|
||||||
|
import { Secret } from "./variants/secret";
|
||||||
|
import { StorageOs } from "./variants/storage-os";
|
||||||
|
import { VsphereVolume } from "./variants/vsphere-volume";
|
||||||
|
|
||||||
|
const deprecatedVolumeTypes = new Set<PodVolumeKind>([
|
||||||
|
"flocker",
|
||||||
|
"gitRepo",
|
||||||
|
"quobyte",
|
||||||
|
"storageos",
|
||||||
|
]);
|
||||||
|
|
||||||
|
interface VolumeVariantProps {
|
||||||
|
pod: Pod;
|
||||||
|
volume: PodVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VolumeVariantRender {
|
||||||
|
kind: PodVolumeKind;
|
||||||
|
element: JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderVolumeVariant({ pod, volume }: VolumeVariantProps): VolumeVariantRender | null {
|
||||||
|
if (volume.awsElasticBlockStore) {
|
||||||
|
return {
|
||||||
|
kind: "awsElasticBlockStore",
|
||||||
|
element: <AwsElasticBlockStore variant={volume.awsElasticBlockStore} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.azureDisk) {
|
||||||
|
return {
|
||||||
|
kind: "azureDisk",
|
||||||
|
element: <AzureDisk variant={volume.azureDisk} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.azureFile) {
|
||||||
|
return {
|
||||||
|
kind: "azureFile",
|
||||||
|
element: <AzureFile variant={volume.azureFile} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.cephfs) {
|
||||||
|
return {
|
||||||
|
kind: "cephfs",
|
||||||
|
element: <CephFs variant={volume.cephfs} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.cinder) {
|
||||||
|
return {
|
||||||
|
kind: "cinder",
|
||||||
|
element: <Cinder variant={volume.cinder} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.configMap) {
|
||||||
|
return {
|
||||||
|
kind: "configMap",
|
||||||
|
element: <ConfigMap variant={volume.configMap} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.csi) {
|
||||||
|
return {
|
||||||
|
kind: "csi",
|
||||||
|
element: <ContainerStorageInterface variant={volume.csi} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.downwardAPI) {
|
||||||
|
return {
|
||||||
|
kind: "downwardAPI",
|
||||||
|
element: <DownwardAPI variant={volume.downwardAPI} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.emptyDir) {
|
||||||
|
return {
|
||||||
|
kind: "emptyDir",
|
||||||
|
element: <EmptyDir variant={volume.emptyDir} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.ephemeral) {
|
||||||
|
return {
|
||||||
|
kind: "ephemeral",
|
||||||
|
element: <Ephemeral variant={volume.ephemeral} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.fc) {
|
||||||
|
return {
|
||||||
|
kind: "fc",
|
||||||
|
element: <FiberChannel variant={volume.fc} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.flexVolume) {
|
||||||
|
return {
|
||||||
|
kind: "flexVolume",
|
||||||
|
element: <FlexVolume variant={volume.flexVolume} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.flocker) {
|
||||||
|
return {
|
||||||
|
kind: "flocker",
|
||||||
|
element: <Flocker variant={volume.flocker} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.gcePersistentDisk) {
|
||||||
|
return {
|
||||||
|
kind: "gcePersistentDisk",
|
||||||
|
element: <GcePersistentDisk variant={volume.gcePersistentDisk} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.gitRepo) {
|
||||||
|
return {
|
||||||
|
kind: "gitRepo",
|
||||||
|
element: <GitRepo variant={volume.gitRepo} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.glusterfs) {
|
||||||
|
return {
|
||||||
|
kind: "glusterfs",
|
||||||
|
element: <GlusterFs variant={volume.glusterfs} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.hostPath) {
|
||||||
|
return {
|
||||||
|
kind: "hostPath",
|
||||||
|
element: <HostPath variant={volume.hostPath} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.iscsi) {
|
||||||
|
return {
|
||||||
|
kind: "iscsi",
|
||||||
|
element: <IScsi variant={volume.iscsi} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.local) {
|
||||||
|
return {
|
||||||
|
kind: "local",
|
||||||
|
element: <Local variant={volume.local} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.nfs) {
|
||||||
|
return {
|
||||||
|
kind: "nfs",
|
||||||
|
element: <NetworkFs variant={volume.nfs} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.persistentVolumeClaim) {
|
||||||
|
return {
|
||||||
|
kind: "persistentVolumeClaim",
|
||||||
|
element: <PersistentVolumeClaim variant={volume.persistentVolumeClaim} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.photonPersistentDisk) {
|
||||||
|
return {
|
||||||
|
kind: "photonPersistentDisk",
|
||||||
|
element: <PhotonPersistentDisk variant={volume.photonPersistentDisk} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.portworxVolume) {
|
||||||
|
return {
|
||||||
|
kind: "portworxVolume",
|
||||||
|
element: <PortworxVolume variant={volume.portworxVolume} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.projected) {
|
||||||
|
return {
|
||||||
|
kind: "projected",
|
||||||
|
element: <Projected variant={volume.projected} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.quobyte) {
|
||||||
|
return {
|
||||||
|
kind: "quobyte",
|
||||||
|
element: <Quobyte variant={volume.quobyte} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.rbd) {
|
||||||
|
return {
|
||||||
|
kind: "rbd",
|
||||||
|
element: <RadosBlockDevice variant={volume.rbd} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.scaleIO) {
|
||||||
|
return {
|
||||||
|
kind: "scaleIO",
|
||||||
|
element: <ScaleIo variant={volume.scaleIO} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.secret) {
|
||||||
|
return {
|
||||||
|
kind: "secret",
|
||||||
|
element: <Secret variant={volume.secret} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.storageos) {
|
||||||
|
return {
|
||||||
|
kind: "storageos",
|
||||||
|
element: <StorageOs variant={volume.storageos} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volume.vsphereVolume) {
|
||||||
|
return {
|
||||||
|
kind: "vsphereVolume",
|
||||||
|
element: <VsphereVolume variant={volume.vsphereVolume} pod={pod} volumeName={volume.name} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function VolumeVariant(props: VolumeVariantProps) {
|
||||||
|
const result = renderVolumeVariant(props);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return <p>Error! Unknown pod volume kind</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { kind, element } = result;
|
||||||
|
const isDeprecated = deprecatedVolumeTypes.has(kind);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Kind">
|
||||||
|
{kind}
|
||||||
|
{isDeprecated && <Icon title="Deprecated" material="warning_amber" />}
|
||||||
|
</DrawerItem>
|
||||||
|
{element}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const AwsElasticBlockStore: VolumeVariantComponent<"awsElasticBlockStore"> = (
|
||||||
|
({ variant: { volumeID, fsType = "ext4" }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Volume ID">
|
||||||
|
{volumeID}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const AzureDisk: VolumeVariantComponent<"azureDisk"> = (
|
||||||
|
({ variant: { diskName, diskURI, kind = "Shared", cachingMode = "None", fsType = "ext4", readonly = false }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name={kind === "Managed" ? "Disk Name" : "VHD blob Name"}>
|
||||||
|
{diskName}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name={kind === "Managed" ? "Resource ID" : "Disk URI"}>
|
||||||
|
{diskURI}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Kind">
|
||||||
|
{kind}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Caching Mode">
|
||||||
|
{cachingMode}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readonly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const AzureFile: VolumeVariantComponent<"azureFile"> = (
|
||||||
|
({ variant: { readOnly = false, secretName, shareName, secretNamespace = "default" }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Secret Name">
|
||||||
|
{secretName}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Share Name">
|
||||||
|
{shareName}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Namespace of Secret">
|
||||||
|
{secretNamespace}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { secretsApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const CephFs: VolumeVariantComponent<"cephfs"> = (
|
||||||
|
({ pod, variant: { monitors, path = "/", user = "admin", secretFile = "/etc/ceph/user.secret", secretRef, readOnly }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Monitors">
|
||||||
|
<ul>
|
||||||
|
{monitors.map(monitor => <li key={monitor}>{monitor}</li>)}
|
||||||
|
</ul>
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Mount Path">
|
||||||
|
{path}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Username">
|
||||||
|
{user}
|
||||||
|
</DrawerItem>
|
||||||
|
{
|
||||||
|
secretRef
|
||||||
|
? (
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Secret"
|
||||||
|
kubeRef={secretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<DrawerItem name="Secret Filepath">
|
||||||
|
{secretFile}
|
||||||
|
</DrawerItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const Cinder: VolumeVariantComponent<"cinder"> = (
|
||||||
|
({ variant: { volumeID, fsType = "ext4" }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Volume ID">
|
||||||
|
{volumeID}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { configMapApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const ConfigMap: VolumeVariantComponent<"configMap"> = (
|
||||||
|
({ pod, variant: { name }}) => (
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Name"
|
||||||
|
kubeRef={{ name }}
|
||||||
|
api={configMapApi}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { secretsApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const ContainerStorageInterface: VolumeVariantComponent<"csi"> = ({
|
||||||
|
pod,
|
||||||
|
variant: {
|
||||||
|
driver,
|
||||||
|
readOnly = false,
|
||||||
|
fsType = "ext4",
|
||||||
|
volumeAttributes = {},
|
||||||
|
nodePublishSecretRef,
|
||||||
|
controllerPublishSecretRef,
|
||||||
|
nodeStageSecretRef,
|
||||||
|
controllerExpandSecretRef,
|
||||||
|
},
|
||||||
|
}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Driver">
|
||||||
|
{driver}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="ReadOnly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Controller Publish Secret"
|
||||||
|
kubeRef={controllerPublishSecretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Controller Expand Secret"
|
||||||
|
kubeRef={controllerExpandSecretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Node Publish Secret"
|
||||||
|
kubeRef={nodePublishSecretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Node Stage Secret"
|
||||||
|
kubeRef={nodeStageSecretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
Object.entries(volumeAttributes)
|
||||||
|
.map(([key, value]) => (
|
||||||
|
<DrawerItem key={key} name={key}>
|
||||||
|
{value}
|
||||||
|
</DrawerItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const DownwardAPI: VolumeVariantComponent<"downwardAPI"> = (
|
||||||
|
({ variant: { items }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Items">
|
||||||
|
<ul>
|
||||||
|
{items.map(item => <li key={item.path}>{item.path}</li>)}
|
||||||
|
</ul>
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const EmptyDir: VolumeVariantComponent<"emptyDir"> = (
|
||||||
|
({ variant: { medium, sizeLimit }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Medium">
|
||||||
|
{medium || "<node's default medium>"}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Size Limit" hidden={!sizeLimit}>
|
||||||
|
{sizeLimit}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { dump } from "js-yaml";
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem, DrawerItemLabels } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const Ephemeral: VolumeVariantComponent<"ephemeral"> = (
|
||||||
|
({ pod, volumeName, variant: { volumeClaimTemplate: { metadata, spec }}}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="PVC Template Name">
|
||||||
|
{pod.getName()}-{volumeName}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItemLabels
|
||||||
|
name="Template Labels"
|
||||||
|
labels={metadata.labels}
|
||||||
|
/>
|
||||||
|
<DrawerItemLabels
|
||||||
|
name="Template Annotations"
|
||||||
|
labels={metadata.annotations}
|
||||||
|
/>
|
||||||
|
<DrawerItem name="Template PVC Spec">
|
||||||
|
{dump(spec)}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const FiberChannel: VolumeVariantComponent<"fc"> = (
|
||||||
|
({ variant: { targetWWNs, lun, fsType = "ext4", readOnly = false }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Target World Wide Names">
|
||||||
|
<ul>
|
||||||
|
{targetWWNs.map(targetWWN => <li key={targetWWN}>{targetWWN}</li>)}
|
||||||
|
</ul>
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Logical Unit Number">
|
||||||
|
{lun.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { secretsApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const FlexVolume: VolumeVariantComponent<"flexVolume"> = (
|
||||||
|
({ pod, variant: { driver, fsType, secretRef, readOnly = false, options }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Driver">
|
||||||
|
{driver}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType || "-- system default --"}
|
||||||
|
</DrawerItem>
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Secret"
|
||||||
|
kubeRef={secretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
{
|
||||||
|
...Object.entries(options)
|
||||||
|
.map(([key, value]) => (
|
||||||
|
<DrawerItem key={key} name={`Option: ${key}`}>
|
||||||
|
{value}
|
||||||
|
</DrawerItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const Flocker: VolumeVariantComponent<"flocker"> = (
|
||||||
|
({ variant: { datasetName }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Dataset Name">
|
||||||
|
{datasetName}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const GcePersistentDisk: VolumeVariantComponent<"gcePersistentDisk"> = (
|
||||||
|
({ variant: { pdName, fsType = "ext4" }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Persistent Disk Name">
|
||||||
|
{pdName}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const GitRepo: VolumeVariantComponent<"gitRepo"> = (
|
||||||
|
({ variant: { repository, revision }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Repository URL">
|
||||||
|
{repository}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Commit Hash">
|
||||||
|
{revision}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const GlusterFs: VolumeVariantComponent<"glusterfs"> = (
|
||||||
|
({ variant: { endpoints, path, readOnly = false }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Endpoints object name">
|
||||||
|
{endpoints}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Glusterfs volume name">
|
||||||
|
{path}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly Mountpoint">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const HostPath: VolumeVariantComponent<"hostPath"> = (
|
||||||
|
({ variant: { path, type }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Node's Host Filesystem Path">
|
||||||
|
{path}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Check Behaviour">
|
||||||
|
{type || "-- none --"}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const IScsi: VolumeVariantComponent<"iscsi"> = (
|
||||||
|
({ variant: { targetPortal, iqn, lun, fsType = "ext4", readOnly = false, chapAuthDiscovery, chapAuthSession, secretRef }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Target Address">
|
||||||
|
{targetPortal}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="iSCSI qualified name">
|
||||||
|
{iqn}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Logical Unit Number">
|
||||||
|
{lun.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
{chapAuthDiscovery && (
|
||||||
|
<DrawerItem name="CHAP Discovery Authentication">
|
||||||
|
{chapAuthDiscovery.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
)}
|
||||||
|
{chapAuthSession && (
|
||||||
|
<DrawerItem name="CHAP Session Authentication">
|
||||||
|
{chapAuthSession.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
)}
|
||||||
|
{ secretRef && (
|
||||||
|
<DrawerItem name="CHAP Secret">
|
||||||
|
{secretRef.name}
|
||||||
|
</DrawerItem>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const Local: VolumeVariantComponent<"local"> = (
|
||||||
|
({ variant: { path }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Path">
|
||||||
|
{path}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const NetworkFs: VolumeVariantComponent<"nfs"> = (
|
||||||
|
({ variant: { server, path, readOnly = false }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Server">
|
||||||
|
{server}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Path">
|
||||||
|
{path}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { pvcApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const PersistentVolumeClaim: VolumeVariantComponent<"persistentVolumeClaim"> = (
|
||||||
|
({ pod, variant: { claimName }}) => (
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Name"
|
||||||
|
kubeRef={{ name: claimName }}
|
||||||
|
api={pvcApi}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const PhotonPersistentDisk: VolumeVariantComponent<"photonPersistentDisk"> = (
|
||||||
|
({ variant: { pdID, fsType = "ext4" }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Persistent Disk ID">
|
||||||
|
{pdID}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const PortworxVolume: VolumeVariantComponent<"portworxVolume"> = (
|
||||||
|
({ variant: { volumeID, fsType = "ext4", readOnly = false }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Volume ID">
|
||||||
|
{volumeID}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem, DrawerTitle } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const Projected: VolumeVariantComponent<"projected"> = (
|
||||||
|
({ variant: { sources, defaultMode }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Default Mount Mode">
|
||||||
|
0o{defaultMode.toString(8)}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Sources">
|
||||||
|
{
|
||||||
|
sources.map(({ secret, downwardAPI, configMap, serviceAccountToken }, index) => (
|
||||||
|
<React.Fragment key={index}>
|
||||||
|
{secret && (
|
||||||
|
<>
|
||||||
|
<DrawerTitle size="sub-title">Secret</DrawerTitle>
|
||||||
|
<DrawerItem name="Name">
|
||||||
|
{secret.name}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Items">
|
||||||
|
<ul>
|
||||||
|
{secret.items?.map(({ key, path }) => (
|
||||||
|
<li key={key}>
|
||||||
|
{key} ⇢ {path}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{downwardAPI && (
|
||||||
|
<>
|
||||||
|
<DrawerTitle size="sub-title">Downward API</DrawerTitle>
|
||||||
|
<DrawerItem name="Items">
|
||||||
|
<ul>
|
||||||
|
{downwardAPI.items?.map(({ path }) => (
|
||||||
|
<li key={path}>
|
||||||
|
{path}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{configMap && (
|
||||||
|
<>
|
||||||
|
<DrawerTitle size="sub-title">Config Map</DrawerTitle>
|
||||||
|
<DrawerItem name="Name">
|
||||||
|
{configMap.name}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Items">
|
||||||
|
<ul>
|
||||||
|
{configMap.items?.map(({ key, path }) => (
|
||||||
|
<li key={key}>
|
||||||
|
{key} ⇢ {path}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{serviceAccountToken && (
|
||||||
|
<>
|
||||||
|
<DrawerTitle size="sub-title">Service Account Token</DrawerTitle>
|
||||||
|
<DrawerItem name="Audience" hidden={!serviceAccountToken.audience}>
|
||||||
|
{serviceAccountToken.audience}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Expiration">
|
||||||
|
{String(serviceAccountToken.expirationSeconds || (60*60 /* an hour */))}s
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Path">
|
||||||
|
{serviceAccountToken.path}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const Quobyte: VolumeVariantComponent<"quobyte"> = (
|
||||||
|
({ variant: { registry, volume, readOnly = false, user = "serviceaccount", group, tenant }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Registry">
|
||||||
|
{registry}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Volume">
|
||||||
|
{volume}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="User">
|
||||||
|
{user}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Group">
|
||||||
|
{group ?? "-- no group --"}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Tenant" hidden={!tenant}>
|
||||||
|
{tenant}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { secretsApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const RadosBlockDevice: VolumeVariantComponent<"rbd"> = (
|
||||||
|
({ pod, variant: { monitors, image, fsType = "ext4", pool = "rbd", user = "admin", keyring = "/etc/ceph/keyright", secretRef, readOnly = false }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Ceph Monitors">
|
||||||
|
<ul>
|
||||||
|
{monitors.map(monitor => <li key={monitor}>{monitor}</li>)}
|
||||||
|
</ul>
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Image">
|
||||||
|
{image}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Pool">
|
||||||
|
{pool}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="User">
|
||||||
|
{user}
|
||||||
|
</DrawerItem>
|
||||||
|
{
|
||||||
|
secretRef
|
||||||
|
? (
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Authentication Secret"
|
||||||
|
kubeRef={secretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<DrawerItem name="Keyright Path">
|
||||||
|
{keyring}
|
||||||
|
</DrawerItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { secretsApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const ScaleIo: VolumeVariantComponent<"scaleIO"> = (
|
||||||
|
({ pod, variant: { gateway, system, secretRef, sslEnabled = false, protectionDomain, storagePool, storageMode = "ThinProvisioned", volumeName, fsType = "xfs", readOnly = false }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Gateway">
|
||||||
|
{gateway}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="System">
|
||||||
|
{system}
|
||||||
|
</DrawerItem>
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Name"
|
||||||
|
kubeRef={secretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
<DrawerItem name="SSL Enabled">
|
||||||
|
{sslEnabled.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Protection Domain Name" hidden={!protectionDomain}>
|
||||||
|
{protectionDomain}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Storage Pool" hidden={!storagePool}>
|
||||||
|
{storagePool}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Storage Mode" hidden={!storageMode}>
|
||||||
|
{storageMode}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Volume Name">
|
||||||
|
{volumeName}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem Type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { secretsApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const Secret: VolumeVariantComponent<"secret"> = (
|
||||||
|
({ pod, variant: { secretName, items = [], defaultMode = 0o644, optional = false }}) => (
|
||||||
|
<>
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Name"
|
||||||
|
kubeRef={{ name: secretName }}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
<DrawerItem name="Items" hidden={items.length === 0}>
|
||||||
|
<ul>
|
||||||
|
{items.map(({ key }) => <li key={key}>{key}</li>)}
|
||||||
|
</ul>
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Default File Mode">
|
||||||
|
0o{defaultMode.toString(8)}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Optional">
|
||||||
|
{optional.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { secretsApi } from "../../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import { LocalRef, VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const StorageOs: VolumeVariantComponent<"storageos"> = (
|
||||||
|
({ pod, variant: { volumeName, volumeNamespace, fsType = "ext4", readOnly = false, secretRef }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Volume Name">
|
||||||
|
{volumeName}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Volume Namespace" hidden={volumeNamespace === "default"}>
|
||||||
|
{
|
||||||
|
volumeNamespace === volumeName
|
||||||
|
? "- no default behaviour -"
|
||||||
|
: volumeNamespace || pod.getNs()
|
||||||
|
}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Readonly">
|
||||||
|
{readOnly.toString()}
|
||||||
|
</DrawerItem>
|
||||||
|
<LocalRef
|
||||||
|
pod={pod}
|
||||||
|
title="Secret"
|
||||||
|
kubeRef={secretRef}
|
||||||
|
api={secretsApi}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerItem } from "../../../../drawer";
|
||||||
|
import type { VolumeVariantComponent } from "../variant-helpers";
|
||||||
|
|
||||||
|
export const VsphereVolume: VolumeVariantComponent<"vsphereVolume"> = (
|
||||||
|
({ variant: { volumePath, fsType = "ext4", storagePolicyName, storagePolicyID }}) => (
|
||||||
|
<>
|
||||||
|
<DrawerItem name="Virtual Machine Disk Volume">
|
||||||
|
{volumePath}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Filesystem type">
|
||||||
|
{fsType}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Storage Policy Based Management Profile Name" hidden={!storagePolicyName}>
|
||||||
|
{storagePolicyName}
|
||||||
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Storage Policy Based Management Profile ID" hidden={!storagePolicyID}>
|
||||||
|
{storagePolicyID}
|
||||||
|
</DrawerItem>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import React from "react";
|
||||||
|
import type { Pod } from "../../../../../common/k8s-api/endpoints";
|
||||||
|
import { DrawerTitle } from "../../../drawer";
|
||||||
|
import { Icon } from "../../../icon";
|
||||||
|
import { VolumeVariant } from "./variant";
|
||||||
|
|
||||||
|
export interface PodVolumesProps {
|
||||||
|
pod: Pod;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PodVolumes = observer(({ pod }: PodVolumesProps) => {
|
||||||
|
const volumes = pod.getVolumes() ?? [];
|
||||||
|
|
||||||
|
if (volumes.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DrawerTitle>Volumes</DrawerTitle>
|
||||||
|
{volumes.map(volume => (
|
||||||
|
<div key={volume.name} className="volume">
|
||||||
|
<div className="title flex gaps">
|
||||||
|
<Icon small material="storage" />
|
||||||
|
<span>{volume.name}</span>
|
||||||
|
</div>
|
||||||
|
<VolumeVariant pod={pod} volume={volume} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
@ -131,7 +131,7 @@ export class PodDetailsList extends React.Component<PodDetailsListProps> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="PodDetailsList flex column">
|
<div className="PodDetailsList flex column">
|
||||||
<DrawerTitle title="Pods" />
|
<DrawerTitle>Pods</DrawerTitle>
|
||||||
<Table
|
<Table
|
||||||
tableId="workloads_pod_details_list"
|
tableId="workloads_pod_details_list"
|
||||||
items={pods}
|
items={pods}
|
||||||
|
|||||||
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
import "./pod-details-secrets.scss";
|
import "./pod-details-secrets.scss";
|
||||||
|
|
||||||
import React, { Component } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { autorun, observable, makeObservable } from "mobx";
|
import { reaction } from "mobx";
|
||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Pod, Secret, secretsApi } from "../../../common/k8s-api/endpoints";
|
import { Pod, Secret, secretsApi } from "../../../common/k8s-api/endpoints";
|
||||||
import { getDetailsUrl } from "../kube-detail-params";
|
import { getDetailsUrl } from "../kube-detail-params";
|
||||||
|
|
||||||
@ -16,59 +16,50 @@ export interface PodDetailsSecretsProps {
|
|||||||
pod: Pod;
|
pod: Pod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
export const PodDetailsSecrets = observer(({ pod }: PodDetailsSecretsProps) => {
|
||||||
export class PodDetailsSecrets extends Component<PodDetailsSecretsProps> {
|
const [secrets, setSecrets] = useState(new Map<string, Secret>());
|
||||||
@observable secrets: Map<string, Secret> = observable.map<string, Secret>();
|
|
||||||
|
|
||||||
componentDidMount(): void {
|
useEffect(() => (
|
||||||
disposeOnUnmount(this, [
|
reaction(
|
||||||
autorun(async () => {
|
() => pod.getSecrets(),
|
||||||
const { pod } = this.props;
|
async (secretNames) => {
|
||||||
|
const results = await Promise.allSettled(
|
||||||
const secrets = await Promise.all(
|
secretNames.map(secretName => secretsApi.get({
|
||||||
pod.getSecrets().map(secretName => secretsApi.get({
|
|
||||||
name: secretName,
|
name: secretName,
|
||||||
namespace: pod.getNs(),
|
namespace: pod.getNs(),
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
secrets.forEach(secret => secret && this.secrets.set(secret.getName(), secret));
|
setSecrets(new Map(
|
||||||
}),
|
results
|
||||||
]);
|
.filter(result => result.status === "fulfilled" && result.value)
|
||||||
}
|
.map(result => (result as PromiseFulfilledResult<Secret>).value)
|
||||||
|
.map(secret => [secret.getName(), secret]),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fireImmediately: true,
|
||||||
|
})
|
||||||
|
), []);
|
||||||
|
|
||||||
constructor(props: PodDetailsSecretsProps) {
|
const renderSecret = (name: string) => {
|
||||||
super(props);
|
const secret = secrets.get(name);
|
||||||
makeObservable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
if (!secret) {
|
||||||
const { pod } = this.props;
|
return <span key={name}>{name}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="PodDetailsSecrets">
|
|
||||||
{
|
|
||||||
pod.getSecrets().map(secretName => {
|
|
||||||
const secret = this.secrets.get(secretName);
|
|
||||||
|
|
||||||
if (secret) {
|
|
||||||
return this.renderSecretLink(secret);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<span key={secretName}>{secretName}</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected renderSecretLink(secret: Secret) {
|
|
||||||
return (
|
return (
|
||||||
<Link key={secret.getId()} to={getDetailsUrl(secret.selfLink)}>
|
<Link key={secret.getId()} to={getDetailsUrl(secret.selfLink)}>
|
||||||
{secret.getName()}
|
{secret.getName()}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
return (
|
||||||
|
<div className="PodDetailsSecrets">
|
||||||
|
{pod.getSecrets().map(renderSecret)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
@ -10,14 +10,13 @@ import kebabCase from "lodash/kebabCase";
|
|||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { observable, reaction, makeObservable } from "mobx";
|
import { observable, reaction, makeObservable } from "mobx";
|
||||||
import { type IPodMetrics, nodesApi, Pod, pvcApi, configMapApi, getMetricsForPods } from "../../../common/k8s-api/endpoints";
|
import { type IPodMetrics, nodesApi, Pod, getMetricsForPods } from "../../../common/k8s-api/endpoints";
|
||||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||||
import { Badge } from "../badge";
|
import { Badge } from "../badge";
|
||||||
import { boundMethod, cssNames, toJS } from "../../utils";
|
import { boundMethod, cssNames, toJS } from "../../utils";
|
||||||
import { PodDetailsContainer } from "./pod-details-container";
|
import { PodDetailsContainer } from "./pod-details-container";
|
||||||
import { PodDetailsAffinities } from "./pod-details-affinities";
|
import { PodDetailsAffinities } from "./pod-details-affinities";
|
||||||
import { PodDetailsTolerations } from "./pod-details-tolerations";
|
import { PodDetailsTolerations } from "./pod-details-tolerations";
|
||||||
import { Icon } from "../icon";
|
|
||||||
import { PodDetailsSecrets } from "./pod-details-secrets";
|
import { PodDetailsSecrets } from "./pod-details-secrets";
|
||||||
import { ResourceMetrics } from "../resource-metrics";
|
import { ResourceMetrics } from "../resource-metrics";
|
||||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||||
@ -28,6 +27,7 @@ import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
|
|||||||
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
import { ClusterMetricsResourceType } from "../../../common/cluster-types";
|
||||||
import { getDetailsUrl } from "../kube-detail-params";
|
import { getDetailsUrl } from "../kube-detail-params";
|
||||||
import logger from "../../../common/logger";
|
import logger from "../../../common/logger";
|
||||||
|
import { PodVolumes } from "./details/volumes/view";
|
||||||
|
|
||||||
export interface PodDetailsProps extends KubeObjectDetailsProps<Pod> {
|
export interface PodDetailsProps extends KubeObjectDetailsProps<Pod> {
|
||||||
}
|
}
|
||||||
@ -73,12 +73,13 @@ export class PodDetails extends React.Component<PodDetailsProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { status, spec } = pod;
|
const { status, spec } = pod;
|
||||||
const { conditions, podIP } = status;
|
const { conditions = [], podIP } = status ?? {};
|
||||||
const podIPs = pod.getIPs();
|
const podIPs = pod.getIPs();
|
||||||
const { nodeName } = spec;
|
const { nodeName } = spec ?? {};
|
||||||
const nodeSelector = pod.getNodeSelectors();
|
const nodeSelector = pod.getNodeSelectors();
|
||||||
const volumes = pod.getVolumes();
|
|
||||||
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod);
|
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod);
|
||||||
|
const initContainers = pod.getInitContainers();
|
||||||
|
const containers = pod.getContainers();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="PodDetails">
|
<div className="PodDetails">
|
||||||
@ -90,26 +91,22 @@ export class PodDetails extends React.Component<PodDetailsProps> {
|
|||||||
<PodCharts/>
|
<PodCharts/>
|
||||||
</ResourceMetrics>
|
</ResourceMetrics>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<KubeObjectMeta object={pod}/>
|
<KubeObjectMeta object={pod}/>
|
||||||
|
|
||||||
<DrawerItem name="Status">
|
<DrawerItem name="Status">
|
||||||
<span className={cssNames("status", kebabCase(pod.getStatusMessage()))}>{pod.getStatusMessage()}</span>
|
<span className={cssNames("status", kebabCase(pod.getStatusMessage()))}>{pod.getStatusMessage()}</span>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerItem name="Node">
|
<DrawerItem name="Node" hidden={!nodeName}>
|
||||||
{nodeName && (
|
<Link to={getDetailsUrl(nodesApi.getUrl({ name: nodeName }))}>
|
||||||
<Link to={getDetailsUrl(nodesApi.getUrl({ name: nodeName }))}>
|
{nodeName}
|
||||||
{nodeName}
|
</Link>
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerItem name="Pod IP">
|
<DrawerItem name="Pod IP">
|
||||||
{podIP}
|
{podIP}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerItem name="Pod IPs" hidden={!podIPs.length} labelsOnly>
|
<DrawerItem name="Pod IPs" hidden={podIPs.length === 0} labelsOnly>
|
||||||
{
|
{podIPs.map(label => <Badge key={label} label={label} />)}
|
||||||
podIPs.map(label => (
|
|
||||||
<Badge key={label} label={label}/>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerItem name="Priority Class">
|
<DrawerItem name="Priority Class">
|
||||||
{pod.getPriorityClassName()}
|
{pod.getPriorityClassName()}
|
||||||
@ -117,129 +114,55 @@ export class PodDetails extends React.Component<PodDetailsProps> {
|
|||||||
<DrawerItem name="QoS Class">
|
<DrawerItem name="QoS Class">
|
||||||
{pod.getQosClass()}
|
{pod.getQosClass()}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
{conditions &&
|
|
||||||
<DrawerItem name="Conditions" className="conditions" labelsOnly>
|
|
||||||
{
|
|
||||||
conditions.map(condition => {
|
|
||||||
const { type, status, lastTransitionTime } = condition;
|
|
||||||
|
|
||||||
return (
|
<DrawerItem name="Conditions" className="conditions" hidden={conditions.length === 0} labelsOnly>
|
||||||
<Badge
|
|
||||||
key={type}
|
|
||||||
label={type}
|
|
||||||
disabled={status === "False"}
|
|
||||||
tooltip={`Last transition time: ${lastTransitionTime}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</DrawerItem>
|
|
||||||
}
|
|
||||||
{nodeSelector.length > 0 &&
|
|
||||||
<DrawerItem name="Node Selector">
|
|
||||||
{
|
{
|
||||||
nodeSelector.map(label => (
|
conditions.map(({ type, status, lastTransitionTime }) => (
|
||||||
<Badge key={label} label={label}/>
|
<Badge
|
||||||
|
key={type}
|
||||||
|
label={type}
|
||||||
|
disabled={status === "False"}
|
||||||
|
tooltip={`Last transition time: ${lastTransitionTime}`}
|
||||||
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
}
|
|
||||||
|
<DrawerItem name="Node Selector" hidden={nodeSelector.length === 0}>
|
||||||
|
{nodeSelector.map(label => <Badge key={label} label={label} />)}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
<PodDetailsTolerations workload={pod}/>
|
<PodDetailsTolerations workload={pod}/>
|
||||||
<PodDetailsAffinities workload={pod}/>
|
<PodDetailsAffinities workload={pod}/>
|
||||||
|
|
||||||
{pod.getSecrets().length > 0 && (
|
<DrawerItem name="Secrets" hidden={pod.getSecrets().length === 0}>
|
||||||
<DrawerItem name="Secrets">
|
<PodDetailsSecrets pod={pod}/>
|
||||||
<PodDetailsSecrets pod={pod}/>
|
</DrawerItem>
|
||||||
</DrawerItem>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{pod.getInitContainers() && pod.getInitContainers().length > 0 &&
|
{initContainers.length > 0 && (
|
||||||
<DrawerTitle title="Init Containers"/>
|
<>
|
||||||
}
|
<DrawerTitle>Init Containers</DrawerTitle>
|
||||||
{
|
{initContainers.map(container => (
|
||||||
pod.getInitContainers() && pod.getInitContainers().map(container => {
|
|
||||||
return <PodDetailsContainer key={container.name} pod={pod} container={container}/>;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
<DrawerTitle title="Containers"/>
|
|
||||||
{
|
|
||||||
pod.getContainers().map(container => {
|
|
||||||
const { name } = container;
|
|
||||||
const metrics = getItemMetrics(toJS(this.containerMetrics), name);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PodDetailsContainer
|
<PodDetailsContainer
|
||||||
key={name}
|
key={container.name}
|
||||||
pod={pod}
|
pod={pod}
|
||||||
container={container}
|
container={container}
|
||||||
metrics={metrics || null}
|
|
||||||
/>
|
/>
|
||||||
);
|
))}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
{volumes.length > 0 && (
|
|
||||||
<>
|
|
||||||
<DrawerTitle title="Volumes"/>
|
|
||||||
{volumes.map(volume => {
|
|
||||||
const claimName = volume.persistentVolumeClaim ? volume.persistentVolumeClaim.claimName : null;
|
|
||||||
const configMap = volume.configMap ? volume.configMap.name : null;
|
|
||||||
const type = Object.keys(volume)[1];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={volume.name} className="volume">
|
|
||||||
<div className="title flex gaps">
|
|
||||||
<Icon small material="storage"/>
|
|
||||||
<span>{volume.name}</span>
|
|
||||||
</div>
|
|
||||||
<DrawerItem name="Type">
|
|
||||||
{type}
|
|
||||||
</DrawerItem>
|
|
||||||
{ type == "configMap" && (
|
|
||||||
<div>
|
|
||||||
{configMap && (
|
|
||||||
<DrawerItem name="Name">
|
|
||||||
<Link
|
|
||||||
to={getDetailsUrl(configMapApi.getUrl({
|
|
||||||
name: configMap,
|
|
||||||
namespace: pod.getNs(),
|
|
||||||
}))}>{configMap}
|
|
||||||
</Link>
|
|
||||||
</DrawerItem>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{ type === "emptyDir" && (
|
|
||||||
<div>
|
|
||||||
{ volume.emptyDir.medium && (
|
|
||||||
<DrawerItem name="Medium">
|
|
||||||
{volume.emptyDir.medium}
|
|
||||||
</DrawerItem>
|
|
||||||
)}
|
|
||||||
{ volume.emptyDir.sizeLimit && (
|
|
||||||
<DrawerItem name="Size Limit">
|
|
||||||
{volume.emptyDir.sizeLimit}
|
|
||||||
</DrawerItem>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{claimName && (
|
|
||||||
<DrawerItem name="Claim Name">
|
|
||||||
<Link
|
|
||||||
to={getDetailsUrl(pvcApi.getUrl({
|
|
||||||
name: claimName,
|
|
||||||
namespace: pod.getNs(),
|
|
||||||
}))}
|
|
||||||
>{claimName}
|
|
||||||
</Link>
|
|
||||||
</DrawerItem>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<DrawerTitle>Containers</DrawerTitle>
|
||||||
|
{containers.map(container => (
|
||||||
|
<PodDetailsContainer
|
||||||
|
key={container.name}
|
||||||
|
pod={pod}
|
||||||
|
container={container}
|
||||||
|
metrics={getItemMetrics(toJS(this.containerMetrics), container.name)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<PodVolumes pod={pod} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,21 +6,30 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { DrawerItem, DrawerItemProps } from "./drawer-item";
|
import { DrawerItem, DrawerItemProps } from "./drawer-item";
|
||||||
import { Badge } from "../badge";
|
import { Badge } from "../badge";
|
||||||
|
import { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||||
|
|
||||||
export interface DrawerItemLabelsProps extends DrawerItemProps {
|
export interface DrawerItemLabelsProps extends DrawerItemProps {
|
||||||
labels: string[];
|
labels: string[] | Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DrawerItemLabels(props: DrawerItemLabelsProps) {
|
export function DrawerItemLabels(props: DrawerItemLabelsProps) {
|
||||||
const { labels, ...itemProps } = props;
|
const { labels, ...itemProps } = props;
|
||||||
|
|
||||||
if (!labels || !labels.length) {
|
if (!labels || typeof labels !== "object") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const labelStrings = Array.isArray(labels)
|
||||||
|
? labels
|
||||||
|
: KubeObject.stringifyLabels(labels);
|
||||||
|
|
||||||
|
if (labelStrings.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DrawerItem {...itemProps} labelsOnly>
|
<DrawerItem {...itemProps} labelsOnly>
|
||||||
{labels.map(label => <Badge key={label} label={label} title={label}/>)}
|
{labelStrings.map(label => <Badge key={label} label={label} title={label}/>)}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,29 +7,32 @@ import "./drawer-item.scss";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { cssNames, displayBooleans } from "../../utils";
|
import { cssNames, displayBooleans } from "../../utils";
|
||||||
|
|
||||||
export interface DrawerItemProps extends React.HTMLAttributes<any> {
|
export interface DrawerItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
name: React.ReactNode;
|
name: React.ReactNode;
|
||||||
className?: string;
|
|
||||||
title?: string;
|
title?: string;
|
||||||
labelsOnly?: boolean;
|
labelsOnly?: boolean;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean"
|
renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean"
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DrawerItem extends React.Component<DrawerItemProps> {
|
export function DrawerItem({
|
||||||
render() {
|
name,
|
||||||
const { name, title, labelsOnly, children, hidden, className, renderBoolean, ...elemProps } = this.props;
|
title,
|
||||||
|
labelsOnly,
|
||||||
if (hidden) return null;
|
children,
|
||||||
|
hidden = false,
|
||||||
const classNames = cssNames("DrawerItem", className, { labelsOnly });
|
className,
|
||||||
const content = displayBooleans(renderBoolean, children);
|
renderBoolean,
|
||||||
|
...elemProps
|
||||||
return (
|
}: DrawerItemProps) {
|
||||||
<div {...elemProps} className={classNames} title={title}>
|
if (hidden) {
|
||||||
<span className="name">{name}</span>
|
return null;
|
||||||
<span className="value">{content}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div {...elemProps} className={cssNames("DrawerItem", className, { labelsOnly })} title={title}>
|
||||||
|
<span className="name">{name}</span>
|
||||||
|
<span className="value">{displayBooleans(renderBoolean, children)}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.DrawerTitle {
|
.DrawerTitle {
|
||||||
padding: $padding * 1.5 $padding * 3;
|
|
||||||
margin: $margin * 3 (-$margin * 3);
|
margin: $margin * 3 (-$margin * 3);
|
||||||
background: var(--drawerSubtitleBackground);
|
background: var(--drawerSubtitleBackground);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.DrawerTitle.title {
|
||||||
|
padding: $padding * 1.5 $padding * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DrawerTitle.sub-title {
|
||||||
|
padding: $padding $padding * 2;
|
||||||
|
}
|
||||||
@ -3,23 +3,29 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "./drawer-title.scss";
|
import styles from "./drawer-title.module.css";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
|
|
||||||
export interface DrawerTitleProps {
|
export interface DrawerTitleProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
title?: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies how large this title is
|
||||||
|
*
|
||||||
|
* @default "title"
|
||||||
|
*/
|
||||||
|
size?: "sub-title" | "title";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DrawerTitle extends React.Component<DrawerTitleProps> {
|
export function DrawerTitle({ className, children, size = "title" }: DrawerTitleProps) {
|
||||||
render() {
|
return (
|
||||||
const { title, children, className } = this.props;
|
<div className={cssNames(styles.DrawerTitle, className, {
|
||||||
|
[styles.title]: size === "title",
|
||||||
return (
|
[styles["sub-title"]]: size === "sub-title",
|
||||||
<div className={cssNames("DrawerTitle", className)}>
|
})}>
|
||||||
{title || children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,6 @@ interface TabsContextValue<D = any> {
|
|||||||
onChange?(value: D): void;
|
onChange?(value: D): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
|
||||||
|
|
||||||
export interface TabsProps<D = any> extends TabsContextValue<D>, Omit<DOMAttributes<HTMLElement>, "onChange"> {
|
export interface TabsProps<D = any> extends TabsContextValue<D>, Omit<DOMAttributes<HTMLElement>, "onChange"> {
|
||||||
className?: string;
|
className?: string;
|
||||||
center?: boolean;
|
center?: boolean;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export function initCatalogEntityDetailRegistry() {
|
|||||||
components: {
|
components: {
|
||||||
Details: ({ entity }: CatalogEntityDetailsProps<KubernetesCluster>) => (
|
Details: ({ entity }: CatalogEntityDetailsProps<KubernetesCluster>) => (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Kubernetes Information" />
|
<DrawerTitle>Kubernetes Information</DrawerTitle>
|
||||||
<div className="box grow EntityMetadata">
|
<div className="box grow EntityMetadata">
|
||||||
<DrawerItem name="Distribution">
|
<DrawerItem name="Distribution">
|
||||||
{entity.metadata.distro || "unknown"}
|
{entity.metadata.distro || "unknown"}
|
||||||
@ -36,7 +36,7 @@ export function initCatalogEntityDetailRegistry() {
|
|||||||
components: {
|
components: {
|
||||||
Details: ({ entity }: CatalogEntityDetailsProps<WebLink>) => (
|
Details: ({ entity }: CatalogEntityDetailsProps<WebLink>) => (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="More Information" />
|
<DrawerTitle>More Information</DrawerTitle>
|
||||||
<DrawerItem name="URL">
|
<DrawerItem name="URL">
|
||||||
{entity.spec.url}
|
{entity.spec.url}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|||||||
@ -13168,10 +13168,10 @@ type-fest@^0.8.1:
|
|||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||||
|
|
||||||
type-fest@^1.4.0:
|
type-fest@^2.12.0:
|
||||||
version "1.4.0"
|
version "2.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.0.tgz#ce342f58cab9114912f54b493d60ab39c3fc82b6"
|
||||||
integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==
|
integrity sha512-Qe5GRT+n/4GoqCNGGVp5Snapg1Omq3V7irBJB3EaKsp7HWDo5Gv2d/67gfNyV+d5EXD+x/RF5l1h4yJ7qNkcGA==
|
||||||
|
|
||||||
type-is@~1.6.18:
|
type-is@~1.6.18:
|
||||||
version "1.6.18"
|
version "1.6.18"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user