@jfvilas/plugin-kwirth-metrics 0.12.8 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -8
- package/dist/api/KwirthMetricsClient.esm.js +4 -57
- package/dist/api/KwirthMetricsClient.esm.js.map +1 -1
- package/dist/api/types.esm.js.map +1 -1
- package/dist/components/{EntityKwirthMetricsContent/EntityKwirthMetricsContent.esm.js → EntityKwirthMetricsContent.esm.js} +84 -64
- package/dist/components/EntityKwirthMetricsContent.esm.js.map +1 -0
- package/dist/components/{Options/Options.esm.js → Options.esm.js} +1 -1
- package/dist/components/Options.esm.js.map +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.esm.js +4 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +1 -1
- package/dist/plugin.esm.js.map +1 -1
- package/dist/routes.esm.js.map +1 -1
- package/package.json +2 -1
- package/dist/assets/kwirthmetrics-component-not-found.svg +0 -29
- package/dist/components/ClusterList/ClusterList.esm.js +0 -30
- package/dist/components/ClusterList/ClusterList.esm.js.map +0 -1
- package/dist/components/ComponentNotFound/ComponentNotFound.esm.js +0 -63
- package/dist/components/ComponentNotFound/ComponentNotFound.esm.js.map +0 -1
- package/dist/components/EntityKwirthMetricsContent/EntityKwirthMetricsContent.esm.js.map +0 -1
- package/dist/components/EntityKwirthMetricsContent/index.esm.js +0 -2
- package/dist/components/EntityKwirthMetricsContent/index.esm.js.map +0 -1
- package/dist/components/ObjectSelector/ObjectSelector.esm.js +0 -82
- package/dist/components/ObjectSelector/ObjectSelector.esm.js.map +0 -1
- package/dist/components/Options/Options.esm.js.map +0 -1
- package/dist/components/ShowError/ShowError.esm.js +0 -20
- package/dist/components/ShowError/ShowError.esm.js.map +0 -1
- package/dist/components/StatusLog/StatusLog.esm.js +0 -10
- package/dist/components/StatusLog/StatusLog.esm.js.map +0 -1
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@ This package is a Backstage plugin for **showing real-time streamed Kubernetes o
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
## Version compatibility
|
|
6
|
-
|
|
6
|
+
KwirthMetrics is compatible with Kwirth core server versions according to following table.
|
|
7
7
|
|
|
8
8
|
| Plugin Kwirth version | Kwirth version |
|
|
9
9
|
|-|-|
|
|
10
|
-
|0.
|
|
10
|
+
|0.13.0|0.4.131|
|
|
11
11
|
|0.12.8|0.4.45|
|
|
12
|
-
|
|
12
|
+
|0.12.5|0.4.20|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
## What for?
|
|
@@ -39,7 +39,6 @@ This frontend plugin **includes just the visualization of metrics** charts. All
|
|
|
39
39
|
The ability to restart pods is also configured in the app-config (YAML, env or whatever), and **restartig permissions are set independently than chart streaming permissions**.
|
|
40
40
|
The backend plugin is the only responsible for configuration and permissionism, all the capabilities related with showing charts are implemented in the frontend plugin, which is in charge of establishing the connections to the corresponding Kwirth instances (running inside your Kubernetes clusters).
|
|
41
41
|
|
|
42
|
-
|
|
43
42
|
## How does it work?
|
|
44
43
|
Let's explain this by following a user working sequence:
|
|
45
44
|
|
|
@@ -66,7 +65,7 @@ If everyting is correctly configured and tagged, the user should see a list of c
|
|
|
66
65
|
|
|
67
66
|
```bash
|
|
68
67
|
# From your Backstage root directory
|
|
69
|
-
yarn --cwd packages/app add @jfvilas/plugin-kwirth-metrics @jfvilas/plugin-kwirth-common @jfvilas/kwirth-common
|
|
68
|
+
yarn --cwd packages/app add @jfvilas/plugin-kwirth-metrics @jfvilas/plugin-kwirth-common @jfvilas/plugin-kwirth-frontend @jfvilas/kwirth-common
|
|
70
69
|
```
|
|
71
70
|
|
|
72
71
|
3. Make sure the [Kwirth backend plugin](https://www.npmjs.com/package/@jfvilas/plugin-kwirth-backend#configure) is installed and configured.
|
|
@@ -78,13 +77,14 @@ If everyting is correctly configured and tagged, the user should see a list of c
|
|
|
78
77
|
1. Add the KwirthMetrics plugin as a tab in your Entity pages:
|
|
79
78
|
|
|
80
79
|
Firstly, import the plugin module.
|
|
80
|
+
|
|
81
81
|
```typescript
|
|
82
82
|
// In packages/app/src/components/catalog/EntityPage.tsx
|
|
83
83
|
import { EntityKwirthMetricsContent, isKwirthAvailable } from '@jfvilas/plugin-kwirth-metrics';
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
Then, add a tab to your EntityPage (the 'if' is optional, you can keep the 'KwirthMetrics' tab always visible if you prefer to do it that way).
|
|
87
|
-
|
|
87
|
+
```jsx
|
|
88
88
|
// Note: Add to any other Pages as well (e.g. defaultEntityPage or webSiteEntityPage, for example)
|
|
89
89
|
const serviceEntityPage = (
|
|
90
90
|
<EntityLayout>
|
|
@@ -95,6 +95,21 @@ If everyting is correctly configured and tagged, the user should see a list of c
|
|
|
95
95
|
</EntityLayout>
|
|
96
96
|
)
|
|
97
97
|
```
|
|
98
|
+
You can setup some default *viewing* options on the `EntityKwirthMetricsContent` component, so, when the entity loads the default options will be set. These options are:
|
|
99
|
+
- `depth`
|
|
100
|
+
- `width`
|
|
101
|
+
- `interval`
|
|
102
|
+
- `chart`
|
|
103
|
+
(The meaning of these properties are explained at the end of this document)
|
|
104
|
+
|
|
105
|
+
If you want to setup a long-running histogram as a default chart for your entities you should setup your entity page like this:
|
|
106
|
+
```jsx
|
|
107
|
+
...
|
|
108
|
+
<EntityLayout.Route if={isKwirthAvailable} path="/kwirthmetrics" title="KwirthMetrics">
|
|
109
|
+
<EntityKwirthMetricsContent allMetrics={true} enableRestart={false} depth={100} chart={'bar'}/>
|
|
110
|
+
</EntityLayout.Route>
|
|
111
|
+
...
|
|
112
|
+
```
|
|
98
113
|
|
|
99
114
|
2. Label your catalog-info according to one of these two startegies:
|
|
100
115
|
|
|
@@ -102,7 +117,7 @@ If everyting is correctly configured and tagged, the user should see a list of c
|
|
|
102
117
|
|
|
103
118
|
```yaml
|
|
104
119
|
metadata:
|
|
105
|
-
|
|
120
|
+
annotations:
|
|
106
121
|
backstage.io/kubernetes-id: entity001
|
|
107
122
|
```
|
|
108
123
|
|
|
@@ -110,7 +125,7 @@ If everyting is correctly configured and tagged, the user should see a list of c
|
|
|
110
125
|
|
|
111
126
|
```yaml
|
|
112
127
|
metadata:
|
|
113
|
-
|
|
128
|
+
annotations:
|
|
114
129
|
backstage.io/kubernetes-id: 'app=core,artifact=backend'
|
|
115
130
|
```
|
|
116
131
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getVersion, getResources, requestAccess } from '@jfvilas/plugin-kwirth-common';
|
|
1
|
+
import { getInfo, getVersion, getResources, requestAccess } from '@jfvilas/plugin-kwirth-common';
|
|
2
2
|
|
|
3
3
|
class KwirthMetricsClient {
|
|
4
4
|
discoveryApi;
|
|
@@ -7,71 +7,18 @@ class KwirthMetricsClient {
|
|
|
7
7
|
this.discoveryApi = options.discoveryApi;
|
|
8
8
|
this.fetchApi = options.fetchApi;
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
async getInfo() {
|
|
11
|
+
return getInfo(this.discoveryApi, this.fetchApi);
|
|
12
|
+
}
|
|
11
13
|
async getVersion() {
|
|
12
14
|
return getVersion(this.discoveryApi, this.fetchApi);
|
|
13
15
|
}
|
|
14
|
-
// move to common
|
|
15
|
-
// async getVersion(): Promise<string> {
|
|
16
|
-
// try {
|
|
17
|
-
// const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
|
|
18
|
-
// const targetUrl = `${baseUrl}/version`
|
|
19
|
-
// const result = await this.fetchApi.fetch(targetUrl)
|
|
20
|
-
// const data = await result.json()
|
|
21
|
-
// if (!result.ok) {
|
|
22
|
-
// throw new Error(`getVersion error: not ok`)
|
|
23
|
-
// }
|
|
24
|
-
// return data.version
|
|
25
|
-
// }
|
|
26
|
-
// catch (err) {
|
|
27
|
-
// throw new Error(`getVersion error: ${err}`)
|
|
28
|
-
// }
|
|
29
|
-
// }
|
|
30
|
-
// async getResources(entity:Entity): Promise<ClusterValidPods> {
|
|
31
|
-
// try {
|
|
32
|
-
// const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
|
|
33
|
-
// const targetUrl = `${baseUrl}/start`
|
|
34
|
-
// var payload=JSON.stringify(entity)
|
|
35
|
-
// const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})
|
|
36
|
-
// const data = await result.json() as ClusterValidPods
|
|
37
|
-
// if (!result.ok) {
|
|
38
|
-
// throw new Error(`getResources error: not ok`)
|
|
39
|
-
// }
|
|
40
|
-
// return data
|
|
41
|
-
// }
|
|
42
|
-
// catch (err) {
|
|
43
|
-
// throw new Error(`getResources error: ${err}`)
|
|
44
|
-
// }
|
|
45
|
-
// }
|
|
46
16
|
async getResources(entity) {
|
|
47
17
|
return getResources(this.discoveryApi, this.fetchApi, entity);
|
|
48
18
|
}
|
|
49
19
|
async requestAccess(entity, channel, scopes) {
|
|
50
20
|
return requestAccess(this.discoveryApi, this.fetchApi, entity, channel, scopes);
|
|
51
21
|
}
|
|
52
|
-
//+++ move to backstage-common
|
|
53
|
-
// async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {
|
|
54
|
-
// try {
|
|
55
|
-
// const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
|
|
56
|
-
// var targetUrl:URL= new URL (`${baseUrl}/access`)
|
|
57
|
-
// targetUrl.searchParams.append('scopes',scopes.join(','))
|
|
58
|
-
// targetUrl.searchParams.append('channel',channel)
|
|
59
|
-
// var payload=JSON.stringify(entity)
|
|
60
|
-
// const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})
|
|
61
|
-
// const data = await result.json() as ClusterValidPods[]
|
|
62
|
-
// // we reconstruct the 'Map' from string of arrays
|
|
63
|
-
// for (var c of data) {
|
|
64
|
-
// c.accessKeys = new Map(JSON.parse(((c as any).accessKeys)))
|
|
65
|
-
// }
|
|
66
|
-
// if (!result.ok) {
|
|
67
|
-
// throw new Error(`requestAccess error: not ok`)
|
|
68
|
-
// }
|
|
69
|
-
// return data
|
|
70
|
-
// }
|
|
71
|
-
// catch (err) {
|
|
72
|
-
// throw new Error(`requestAccess error: ${err}`)
|
|
73
|
-
// }
|
|
74
|
-
// }
|
|
75
22
|
}
|
|
76
23
|
|
|
77
24
|
export { KwirthMetricsClient };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KwirthMetricsClient.esm.js","sources":["../../src/api/KwirthMetricsClient.ts"],"sourcesContent":["/*\r\nCopyright 2024 Julio Fernandez\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\");\r\nyou may not use this file except in compliance with the License.\r\nYou may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software\r\ndistributed under the License is distributed on an \"AS IS\" BASIS,\r\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\nSee the License for the specific language governing permissions and\r\nlimitations under the License.\r\n*/\r\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'\r\nimport { KwirthMetricsApi } from './types'\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { ClusterValidPods, getResources, getVersion, requestAccess } from '@jfvilas/plugin-kwirth-common'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\n\r\nexport interface KwirthMetricsClientOptions {\r\n discoveryApi: DiscoveryApi\r\n fetchApi: FetchApi\r\n}\r\n\r\nexport class KwirthMetricsClient implements KwirthMetricsApi {\r\n private readonly discoveryApi: DiscoveryApi\r\n private readonly fetchApi: FetchApi\r\n\r\n\r\n constructor(options: KwirthMetricsClientOptions) {\r\n this.discoveryApi = options.discoveryApi\r\n this.fetchApi = options.fetchApi\r\n }\r\n\r\n
|
|
1
|
+
{"version":3,"file":"KwirthMetricsClient.esm.js","sources":["../../src/api/KwirthMetricsClient.ts"],"sourcesContent":["/*\r\nCopyright 2024 Julio Fernandez\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\");\r\nyou may not use this file except in compliance with the License.\r\nYou may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software\r\ndistributed under the License is distributed on an \"AS IS\" BASIS,\r\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\nSee the License for the specific language governing permissions and\r\nlimitations under the License.\r\n*/\r\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'\r\nimport { KwirthMetricsApi } from './types'\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { ClusterValidPods, getInfo, getResources, getVersion, IBackendInfo, requestAccess } from '@jfvilas/plugin-kwirth-common'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\n\r\nexport interface KwirthMetricsClientOptions {\r\n discoveryApi: DiscoveryApi\r\n fetchApi: FetchApi\r\n}\r\n\r\nexport class KwirthMetricsClient implements KwirthMetricsApi {\r\n private readonly discoveryApi: DiscoveryApi\r\n private readonly fetchApi: FetchApi\r\n\r\n\r\n constructor(options: KwirthMetricsClientOptions) {\r\n this.discoveryApi = options.discoveryApi\r\n this.fetchApi = options.fetchApi\r\n }\r\n\r\n async getInfo() : Promise<IBackendInfo> {\r\n return getInfo(this.discoveryApi, this.fetchApi)\r\n }\r\n\r\n async getVersion() : Promise<string> {\r\n return getVersion(this.discoveryApi, this.fetchApi)\r\n }\r\n\r\n async getResources(entity:Entity): Promise<ClusterValidPods> {\r\n return getResources(this.discoveryApi, this.fetchApi, entity)\r\n }\r\n\r\n async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {\r\n return requestAccess(this.discoveryApi, this.fetchApi, entity, channel, scopes)\r\n }\r\n\r\n}\r\n"],"names":[],"mappings":";;AA0BO,MAAM,mBAAA,CAAgD;AAAA,EACxC,YAAA;AAAA,EACA,QAAA;AAAA,EAGjB,YAAY,OAAA,EAAqC;AAC7C,IAAA,IAAA,CAAK,eAAe,OAAA,CAAQ,YAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AAAA,EAC5B;AAAA,EAEA,MAAM,OAAA,GAAkC;AACpC,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,QAAQ,CAAA;AAAA,EACnD;AAAA,EAEA,MAAM,UAAA,GAA+B;AACjC,IAAA,OAAO,UAAA,CAAW,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,QAAQ,CAAA;AAAA,EACtD;AAAA,EAEA,MAAM,aAAa,MAAA,EAA0C;AACzD,IAAA,OAAO,YAAA,CAAa,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,UAAU,MAAM,CAAA;AAAA,EAChE;AAAA,EAEA,MAAM,aAAA,CAAc,MAAA,EAAe,OAAA,EAAgB,MAAA,EAA+D;AAC9G,IAAA,OAAO,cAAc,IAAA,CAAK,YAAA,EAAc,KAAK,QAAA,EAAU,MAAA,EAAQ,SAAS,MAAM,CAAA;AAAA,EAClF;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.esm.js","sources":["../../src/api/types.ts"],"sourcesContent":["/*\r\nCopyright 2024 Julio Fernandez\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\");\r\nyou may not use this file except in compliance with the License.\r\nYou may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software\r\ndistributed under the License is distributed on an \"AS IS\" BASIS,\r\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\nSee the License for the specific language governing permissions and\r\nlimitations under the License.\r\n*/\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { createApiRef } from '@backstage/core-plugin-api'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\nimport { ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\n\r\nexport interface KwirthMetricsApi {\r\n requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]>\r\n getResources(entity:Entity): Promise<ClusterValidPods>\r\n getVersion(): Promise<string>\r\n}\r\n\r\nexport const kwirthMetricsApiRef = createApiRef<KwirthMetricsApi>({\r\n id: 'plugin.kwirthmetrics.api',\r\n})\r\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"types.esm.js","sources":["../../src/api/types.ts"],"sourcesContent":["/*\r\nCopyright 2024 Julio Fernandez\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\");\r\nyou may not use this file except in compliance with the License.\r\nYou may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software\r\ndistributed under the License is distributed on an \"AS IS\" BASIS,\r\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\nSee the License for the specific language governing permissions and\r\nlimitations under the License.\r\n*/\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { createApiRef } from '@backstage/core-plugin-api'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\nimport { ClusterValidPods, IBackendInfo } from '@jfvilas/plugin-kwirth-common'\r\n\r\nexport interface KwirthMetricsApi {\r\n requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]>\r\n getResources(entity:Entity): Promise<ClusterValidPods>\r\n getVersion(): Promise<string>\r\n getInfo(): Promise<IBackendInfo>\r\n}\r\n\r\nexport const kwirthMetricsApiRef = createApiRef<KwirthMetricsApi>({\r\n id: 'plugin.kwirthmetrics.api',\r\n})\r\n"],"names":[],"mappings":";;AA2BO,MAAM,sBAAsB,YAAA,CAA+B;AAAA,EAChE,EAAA,EAAI;AACN,CAAC;;;;"}
|
|
@@ -2,20 +2,13 @@ import React, { useState, useRef } from 'react';
|
|
|
2
2
|
import useAsync from 'react-use/esm/useAsync';
|
|
3
3
|
import { Progress, WarningPanel } from '@backstage/core-components';
|
|
4
4
|
import { useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
5
|
-
import { isKwirthAvailable, ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR } from '@jfvilas/plugin-kwirth-common';
|
|
5
|
+
import { isKwirthAvailable, ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR, getPodList, getContainerList } from '@jfvilas/plugin-kwirth-common';
|
|
6
6
|
import { useEntity, MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react';
|
|
7
|
-
import { kwirthMetricsApiRef } from '
|
|
7
|
+
import { kwirthMetricsApiRef } from '../api/types.esm.js';
|
|
8
8
|
import { SignalMessageLevelEnum, InstanceConfigScopeEnum, InstanceMessageTypeEnum, OpsCommandEnum, accessKeySerialize, InstanceMessageChannelEnum, InstanceMessageFlowEnum, InstanceMessageActionEnum, MetricsConfigModeEnum, InstanceConfigViewEnum, InstanceConfigObjectEnum } from '@jfvilas/kwirth-common';
|
|
9
|
-
import { ComponentNotFound, ErrorType } from '
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { ObjectSelector } from '../ObjectSelector/ObjectSelector.esm.js';
|
|
13
|
-
import { ShowError } from '../ShowError/ShowError.esm.js';
|
|
14
|
-
import { StatusLog } from '../StatusLog/StatusLog.esm.js';
|
|
15
|
-
import { Box, Grid, Card, CardHeader, CardContent, FormControl, Select, MenuItem, Checkbox } from '@material-ui/core';
|
|
16
|
-
import Divider from '@material-ui/core/Divider';
|
|
17
|
-
import IconButton from '@material-ui/core/IconButton';
|
|
18
|
-
import Typography from '@material-ui/core/Typography';
|
|
9
|
+
import { ShowError, ComponentNotFound, ErrorType, ClusterList, KwirthNews, ObjectSelector, StatusLog } from '@jfvilas/plugin-kwirth-frontend';
|
|
10
|
+
import { VERSION } from '../index.esm.js';
|
|
11
|
+
import { Box, Grid, Card, CardHeader, Typography, FormControl, Select, MenuItem, Checkbox, Divider, CardContent, IconButton, Tooltip as Tooltip$1 } from '@material-ui/core';
|
|
19
12
|
import PlayIcon from '@material-ui/icons/PlayArrow';
|
|
20
13
|
import PauseIcon from '@material-ui/icons/Pause';
|
|
21
14
|
import StopIcon from '@material-ui/icons/Stop';
|
|
@@ -23,14 +16,15 @@ import InfoIcon from '@material-ui/icons/Info';
|
|
|
23
16
|
import WarningIcon from '@material-ui/icons/Warning';
|
|
24
17
|
import ErrorIcon from '@material-ui/icons/Error';
|
|
25
18
|
import RefreshIcon from '@material-ui/icons/Refresh';
|
|
26
|
-
import KwirthMetricsLogo from '
|
|
19
|
+
import KwirthMetricsLogo from '../assets/kwirthmetrics-logo.svg';
|
|
27
20
|
import { BarChart, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Bar, LabelList, AreaChart, Area, LineChart, Line, ResponsiveContainer } from 'recharts';
|
|
21
|
+
import { Options } from './Options.esm.js';
|
|
28
22
|
|
|
29
23
|
const EntityKwirthMetricsContent = (props) => {
|
|
30
24
|
const kwirthMetricsApi = useApi(kwirthMetricsApiRef);
|
|
31
25
|
const alertApi = useApi(alertApiRef);
|
|
32
26
|
const { entity } = useEntity();
|
|
33
|
-
const [
|
|
27
|
+
const [validClusters, setValidClusters] = useState([]);
|
|
34
28
|
const [selectedClusterName, setSelectedClusterName] = useState("");
|
|
35
29
|
const [selectedNamespaces, setSelectedNamespaces] = useState([]);
|
|
36
30
|
const [selectedPodNames, setSelectedPodNames] = useState([]);
|
|
@@ -44,10 +38,19 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
44
38
|
const [statusMessages, setStatusMessages] = useState([]);
|
|
45
39
|
const [websocket, setWebsocket] = useState();
|
|
46
40
|
const [instance, setInstance] = useState();
|
|
47
|
-
const kwirthMetricsOptionsRef = useRef({
|
|
41
|
+
const kwirthMetricsOptionsRef = useRef({
|
|
42
|
+
depth: props.depth !== void 0 ? props.depth : 10,
|
|
43
|
+
width: props.width !== void 0 ? props.width : 3,
|
|
44
|
+
interval: props.interval !== void 0 ? props.interval : 15,
|
|
45
|
+
chart: props.chart !== void 0 ? props.chart : "area",
|
|
46
|
+
aggregate: false,
|
|
47
|
+
merge: false,
|
|
48
|
+
stack: false
|
|
49
|
+
});
|
|
48
50
|
const [showStatusDialog, setShowStatusDialog] = useState(false);
|
|
49
51
|
const [statusLevel, setStatusLevel] = useState(SignalMessageLevelEnum.INFO);
|
|
50
52
|
const [backendVersion, setBackendVersion] = useState("");
|
|
53
|
+
const [backendInfo, setBackendInfo] = useState();
|
|
51
54
|
const [_refresh, setRefresh] = useState(0);
|
|
52
55
|
const [allMetrics, setAllMetrics] = useState(
|
|
53
56
|
[
|
|
@@ -61,10 +64,11 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
61
64
|
);
|
|
62
65
|
const { loading, error } = useAsync(async () => {
|
|
63
66
|
if (backendVersion === "") setBackendVersion(await kwirthMetricsApi.getVersion());
|
|
67
|
+
if (!backendInfo) setBackendInfo(await kwirthMetricsApi.getInfo());
|
|
64
68
|
let reqScopes = [InstanceConfigScopeEnum.STREAM];
|
|
65
69
|
if (props.enableRestart) reqScopes.push(InstanceConfigScopeEnum.RESTART);
|
|
66
70
|
let data = await kwirthMetricsApi.requestAccess(entity, "metrics", reqScopes);
|
|
67
|
-
|
|
71
|
+
setValidClusters(data);
|
|
68
72
|
});
|
|
69
73
|
const colours = [
|
|
70
74
|
"#6e5bb8",
|
|
@@ -148,25 +152,32 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
148
152
|
setStarted(false);
|
|
149
153
|
paused.current = true;
|
|
150
154
|
};
|
|
151
|
-
const
|
|
155
|
+
const onClickStop = () => {
|
|
152
156
|
setStarted(false);
|
|
153
157
|
setStopped(true);
|
|
154
158
|
paused.current = false;
|
|
155
159
|
stopMetricsViewer();
|
|
156
160
|
};
|
|
157
161
|
const onSelectCluster = async (clusterName) => {
|
|
162
|
+
if (started) onClickStop();
|
|
158
163
|
if (clusterName) {
|
|
159
164
|
setSelectedClusterName(clusterName);
|
|
160
|
-
setSelectedNamespaces([]);
|
|
161
165
|
setSelectedPodNames([]);
|
|
162
166
|
setSelectedContainerNames([]);
|
|
163
|
-
setMetricsMessages([]);
|
|
164
167
|
setStatusMessages([]);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
cluster.metrics.sort((a, b) => a.metric.startsWith("kwirth") ? -1 : 1);
|
|
168
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === clusterName);
|
|
169
|
+
if (cluster && cluster.pods && cluster.metrics) {
|
|
170
|
+
cluster.metrics.sort((a, _b) => a.metric.startsWith("kwirth") ? -1 : 1);
|
|
169
171
|
setAllMetrics(cluster.metrics);
|
|
172
|
+
let validNamespaces = Array.from(new Set(cluster.pods.map((pod) => pod.namespace)));
|
|
173
|
+
if (validNamespaces.length === 1) {
|
|
174
|
+
setSelectedNamespaces(validNamespaces);
|
|
175
|
+
let podList = getPodList(cluster.pods, validNamespaces);
|
|
176
|
+
setSelectedPodNames(podList.map((pod) => pod.name));
|
|
177
|
+
setSelectedContainerNames(getContainerList(cluster.pods, validNamespaces, podList.map((pod) => pod.name)));
|
|
178
|
+
} else {
|
|
179
|
+
setSelectedNamespaces([]);
|
|
180
|
+
}
|
|
170
181
|
}
|
|
171
182
|
}
|
|
172
183
|
};
|
|
@@ -196,24 +207,28 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
196
207
|
setInstance(instanceMessage.instance);
|
|
197
208
|
else {
|
|
198
209
|
let signalMessage = instanceMessage;
|
|
199
|
-
|
|
210
|
+
if (signalMessage.text) {
|
|
211
|
+
alertApi.post({ message: signalMessage.text, severity: "error", display: "transient" });
|
|
212
|
+
}
|
|
200
213
|
}
|
|
201
214
|
} else {
|
|
202
215
|
let signalMessage = instanceMessage;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
216
|
+
if (signalMessage.text) {
|
|
217
|
+
addMessage(signalMessage.level, signalMessage.text);
|
|
218
|
+
switch (signalMessage.level) {
|
|
219
|
+
case SignalMessageLevelEnum.INFO:
|
|
220
|
+
alertApi.post({ message: signalMessage.text, severity: "info", display: "transient" });
|
|
221
|
+
break;
|
|
222
|
+
case SignalMessageLevelEnum.WARNING:
|
|
223
|
+
alertApi.post({ message: signalMessage.text, severity: "warning", display: "transient" });
|
|
224
|
+
break;
|
|
225
|
+
case SignalMessageLevelEnum.ERROR:
|
|
226
|
+
alertApi.post({ message: signalMessage.text, severity: "error", display: "transient" });
|
|
227
|
+
break;
|
|
228
|
+
default:
|
|
229
|
+
alertApi.post({ message: signalMessage.text, severity: "success", display: "transient" });
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
217
232
|
}
|
|
218
233
|
}
|
|
219
234
|
break;
|
|
@@ -249,12 +264,12 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
249
264
|
}
|
|
250
265
|
};
|
|
251
266
|
const websocketOnOpen = (ws) => {
|
|
252
|
-
let cluster =
|
|
267
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
253
268
|
if (!cluster) {
|
|
254
269
|
addMessage(SignalMessageLevelEnum.ERROR, "Cluster not found");
|
|
255
270
|
return;
|
|
256
271
|
}
|
|
257
|
-
let pods = cluster.
|
|
272
|
+
let pods = cluster.pods.filter((p2) => selectedNamespaces.includes(p2.namespace));
|
|
258
273
|
if (!pods || pods.length === 0) {
|
|
259
274
|
addMessage(SignalMessageLevelEnum.ERROR, "Pod not found");
|
|
260
275
|
return;
|
|
@@ -298,7 +313,7 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
298
313
|
}
|
|
299
314
|
};
|
|
300
315
|
const startMetricsViewer = () => {
|
|
301
|
-
let cluster =
|
|
316
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
302
317
|
if (!cluster) {
|
|
303
318
|
addMessage(SignalMessageLevelEnum.ERROR, "Cluster not found");
|
|
304
319
|
return;
|
|
@@ -328,28 +343,25 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
328
343
|
};
|
|
329
344
|
const actionButtons = () => {
|
|
330
345
|
let hasStreamKey = false, hasRestartKey = false;
|
|
331
|
-
let cluster =
|
|
346
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
332
347
|
if (cluster) {
|
|
333
348
|
hasStreamKey = Boolean(cluster.accessKeys.has(InstanceConfigScopeEnum.STREAM));
|
|
334
349
|
hasRestartKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART));
|
|
335
350
|
}
|
|
336
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, props.enableRestart && /* @__PURE__ */ React.createElement(IconButton, { title: "Restart", onClick: onClickRestart, disabled: selectedPodNames.length === 0 || !hasRestartKey || !websocket || !started }, /* @__PURE__ */ React.createElement(RefreshIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: clickStart, title: "Play", disabled: started || !paused || selectedPodNames.length === 0 || selectedMetrics.length == 0 || !hasStreamKey }, /* @__PURE__ */ React.createElement(PlayIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: clickPause, title: "Pause", disabled: !(started && !paused.current && selectedPodNames.length === 0) }, /* @__PURE__ */ React.createElement(PauseIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick:
|
|
351
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, props.enableRestart && /* @__PURE__ */ React.createElement(IconButton, { title: "Restart", onClick: onClickRestart, disabled: selectedPodNames.length === 0 || !hasRestartKey || !websocket || !started }, /* @__PURE__ */ React.createElement(RefreshIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: clickStart, title: "Play", disabled: started || !paused || selectedPodNames.length === 0 || selectedMetrics.length == 0 || !hasStreamKey }, /* @__PURE__ */ React.createElement(PlayIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: clickPause, title: "Pause", disabled: !(started && !paused.current && selectedPodNames.length === 0) }, /* @__PURE__ */ React.createElement(PauseIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: onClickStop, title: "Stop", disabled: stopped || selectedPodNames.length === 0 }, /* @__PURE__ */ React.createElement(StopIcon, null)));
|
|
337
352
|
};
|
|
338
353
|
const onMetricsChange = (event) => {
|
|
339
354
|
setSelectedMetrics(event.target.value);
|
|
340
355
|
};
|
|
341
|
-
const metricsSelector = () => {
|
|
342
|
-
let disabled = selectedClusterName === "" || selectedNamespaces.length === 0;
|
|
343
|
-
return /* @__PURE__ */ React.createElement(FormControl, { style: { marginLeft: 16, width: "300px" }, size: "small" }, /* @__PURE__ */ React.createElement(Select, { value: selectedMetrics, MenuProps: { variant: "menu" }, multiple: true, onChange: onMetricsChange, renderValue: (selected) => selected.join(", "), disabled: disabled || started }, allMetrics.map(
|
|
344
|
-
(m) => /* @__PURE__ */ React.createElement(MenuItem, { key: m.metric, value: m.metric, style: { marginTop: "-6px", marginBottom: "-6px" } }, /* @__PURE__ */ React.createElement(Checkbox, { checked: selectedMetrics.includes(m.metric), style: { marginTop: "-6px", marginBottom: "-6px" } }), /* @__PURE__ */ React.createElement(Typography, { style: { marginTop: "-6px", marginBottom: "-6px" } }, m.metric))
|
|
345
|
-
)));
|
|
346
|
-
};
|
|
347
356
|
const statusButtons = (title) => {
|
|
348
357
|
const show = (level) => {
|
|
349
358
|
setShowStatusDialog(true);
|
|
350
359
|
setStatusLevel(level);
|
|
351
360
|
};
|
|
352
|
-
|
|
361
|
+
const prepareText = (txt) => {
|
|
362
|
+
return txt ? txt.length > 25 ? txt.substring(0, 25) + "..." : txt : "N/A";
|
|
363
|
+
};
|
|
364
|
+
return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, prepareText(title))), /* @__PURE__ */ React.createElement(Grid, { item: true, style: { marginTop: "-8px" } }, /* @__PURE__ */ React.createElement(IconButton, { title: "info", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.INFO), onClick: () => show(SignalMessageLevelEnum.INFO) }, /* @__PURE__ */ React.createElement(InfoIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.INFO) ? "blue" : "#BDBDBD" } })), /* @__PURE__ */ React.createElement(IconButton, { title: "warning", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.WARNING), onClick: () => show(SignalMessageLevelEnum.WARNING), style: { marginLeft: "-16px" } }, /* @__PURE__ */ React.createElement(WarningIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.WARNING) ? "gold" : "#BDBDBD" } })), /* @__PURE__ */ React.createElement(IconButton, { title: "error", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.ERROR), onClick: () => show(SignalMessageLevelEnum.ERROR), style: { marginLeft: "-16px" } }, /* @__PURE__ */ React.createElement(ErrorIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.ERROR) ? "red" : "#BDBDBD" } }))));
|
|
353
365
|
};
|
|
354
366
|
const statusClear = (level) => {
|
|
355
367
|
setStatusMessages(statusMessages.filter((m) => m.level !== level));
|
|
@@ -382,7 +394,7 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
382
394
|
switch (options.chart) {
|
|
383
395
|
case "value":
|
|
384
396
|
height = 40 + series.length * 80;
|
|
385
|
-
result = /* @__PURE__ */ React.createElement(Grid,
|
|
397
|
+
result = /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Typography, null, series.map((serie, index) => {
|
|
386
398
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, null, serie[serie.length - 1].value), /* @__PURE__ */ React.createElement(Typography, null, names[index]));
|
|
387
399
|
})));
|
|
388
400
|
break;
|
|
@@ -400,7 +412,16 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
400
412
|
));
|
|
401
413
|
break;
|
|
402
414
|
}
|
|
403
|
-
|
|
415
|
+
let title = metric.metric.replaceAll("_", " ");
|
|
416
|
+
title = title[0].toLocaleUpperCase() + title.substring(1);
|
|
417
|
+
title = title.replaceAll("cpu", "CPU");
|
|
418
|
+
title = title.replaceAll(" fs ", " FS ");
|
|
419
|
+
title = title.replaceAll(" io ", " IO ");
|
|
420
|
+
title = title.replaceAll("oom", "OOM");
|
|
421
|
+
title = title.replaceAll("nvm", "NVM");
|
|
422
|
+
title = title.replaceAll("rss", "RSS");
|
|
423
|
+
title = title.replaceAll("failcnt", "fail count");
|
|
424
|
+
return /* @__PURE__ */ React.createElement(Grid, { style: { width: "100%", marginBottom: 32 } }, /* @__PURE__ */ React.createElement(Tooltip$1, { title: /* @__PURE__ */ React.createElement(Typography, { style: { fontSize: 12 } }, /* @__PURE__ */ React.createElement("b", null, metric.metric), /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("br", null), metric.help) }, /* @__PURE__ */ React.createElement(Typography, { align: "center" }, title)), /* @__PURE__ */ React.createElement(ResponsiveContainer, { height, key: metric + JSON.stringify(names) }, result));
|
|
404
425
|
};
|
|
405
426
|
const showMetrics = (options) => {
|
|
406
427
|
if (!metricsMessages || metricsMessages.length === 0) {
|
|
@@ -409,6 +430,8 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
409
430
|
else
|
|
410
431
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, started ? /* @__PURE__ */ React.createElement(Typography, null, "Waiting for first data, be patient...") : /* @__PURE__ */ React.createElement(Typography, null, "Configure ", /* @__PURE__ */ React.createElement("b", null, "chart options"), ", select some ", /* @__PURE__ */ React.createElement("b", null, "metrics on top"), ", and ", /* @__PURE__ */ React.createElement("b", null, "press PLAY"), " on top-right button to start viewing."));
|
|
411
432
|
}
|
|
433
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
434
|
+
if (!cluster) return;
|
|
412
435
|
let data = /* @__PURE__ */ new Map();
|
|
413
436
|
for (let metricsMessage of metricsMessages) {
|
|
414
437
|
let ts = new Date(metricsMessage.timestamp);
|
|
@@ -428,10 +451,11 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
428
451
|
var firstAsset = assetNames[0];
|
|
429
452
|
var allMetrics2 = Array.from(new Set(data.get(firstAsset).keys()));
|
|
430
453
|
for (let metric of allMetrics2) {
|
|
454
|
+
let metricDefinition = cluster.metrics?.find((m) => m.metric === metric);
|
|
431
455
|
var series = assetNames.map((an) => {
|
|
432
456
|
return data.get(an).get(metric);
|
|
433
457
|
});
|
|
434
|
-
allCharts.push(/* @__PURE__ */ React.createElement(React.Fragment, null, addChart(options,
|
|
458
|
+
allCharts.push(/* @__PURE__ */ React.createElement(React.Fragment, null, addChart(options, metricDefinition, assetNames, series, "")));
|
|
435
459
|
}
|
|
436
460
|
let rows = [];
|
|
437
461
|
for (let i2 = 0; i2 < allCharts.length; i2 += options.width) {
|
|
@@ -442,7 +466,8 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
442
466
|
let allCharts2 = Array.from(data.keys()).map((asset, index) => {
|
|
443
467
|
return Array.from(data.get(asset)?.keys()).map((metric) => {
|
|
444
468
|
var serie = data.get(asset)?.get(metric);
|
|
445
|
-
|
|
469
|
+
let metricDefinition = cluster.metrics?.find((m) => m.metric === metric);
|
|
470
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, addChart(options, metricDefinition, [asset], [serie], colours[index]));
|
|
446
471
|
});
|
|
447
472
|
});
|
|
448
473
|
let rows = [];
|
|
@@ -467,7 +492,7 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
467
492
|
}]);
|
|
468
493
|
};
|
|
469
494
|
const onClickRestart = () => {
|
|
470
|
-
let cluster =
|
|
495
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
471
496
|
if (!cluster) {
|
|
472
497
|
addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
|
|
473
498
|
return;
|
|
@@ -481,7 +506,7 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
481
506
|
addMessage(SignalMessageLevelEnum.ERROR, "No instance has been established");
|
|
482
507
|
return;
|
|
483
508
|
}
|
|
484
|
-
let pods = cluster.
|
|
509
|
+
let pods = cluster.pods.filter((pod) => selectedNamespaces.includes(pod.namespace));
|
|
485
510
|
for (let pod of pods) {
|
|
486
511
|
let om = {
|
|
487
512
|
msgtype: "opsmessage",
|
|
@@ -512,14 +537,9 @@ const EntityKwirthMetricsContent = (props) => {
|
|
|
512
537
|
websocket?.send(JSON.stringify(rm));
|
|
513
538
|
}
|
|
514
539
|
};
|
|
515
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, showError !== "" && /* @__PURE__ */ React.createElement(ShowError, { message: showError, onClose: () => setShowError("") }), loading && /* @__PURE__ */ React.createElement(Progress, null), !isKwirthAvailable(entity) && !loading && error && /* @__PURE__ */ React.createElement(WarningPanel, { title: "An error has ocurred while obtaining data from kuebernetes clusters.", message: error?.message }), !isKwirthAvailable(entity) && !loading && /* @__PURE__ */ React.createElement(MissingAnnotationEmptyState, { readMoreUrl: "https://github.com/jfvilas/kwirth", annotation: [ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR] }), isKwirthAvailable(entity) && !loading &&
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
title: statusButtons(selectedClusterName),
|
|
519
|
-
style: { marginTop: -4, marginBottom: 4, flexShrink: 0 },
|
|
520
|
-
action: actionButtons()
|
|
521
|
-
}
|
|
522
|
-
), /* @__PURE__ */ React.createElement(Typography, { style: { marginLeft: 16, marginBottom: 4 } }, /* @__PURE__ */ React.createElement(ObjectSelector, { cluster: clusterValidPods.find((cluster) => cluster.name === selectedClusterName), onSelect: onSelectObject, disabled: selectedClusterName === "" || started || paused.current, selectedNamespaces, selectedPodNames, selectedContainerNames, scope: InstanceConfigScopeEnum.STREAM })), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(CardContent, { style: { overflow: "auto" } }, showMetrics(kwirthMetricsOptionsRef.current)))))), showStatusDialog && /* @__PURE__ */ React.createElement(StatusLog, { level: statusLevel, onClose: () => setShowStatusDialog(false), statusMessages, onClear: statusClear }));
|
|
540
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, showError !== "" && /* @__PURE__ */ React.createElement(ShowError, { message: showError, onClose: () => setShowError("") }), loading && /* @__PURE__ */ React.createElement(Progress, null), !isKwirthAvailable(entity) && !loading && error && /* @__PURE__ */ React.createElement(WarningPanel, { title: "An error has ocurred while obtaining data from kuebernetes clusters.", message: error?.message }), !isKwirthAvailable(entity) && !loading && /* @__PURE__ */ React.createElement(MissingAnnotationEmptyState, { readMoreUrl: "https://github.com/jfvilas/kwirth", annotation: [ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR] }), isKwirthAvailable(entity) && !loading && validClusters && validClusters.length === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_CLUSTERS, entity }), isKwirthAvailable(entity) && !loading && validClusters && validClusters.length > 0 && validClusters.reduce((sum, cluster) => sum + cluster.pods.length, 0) === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_PODS, entity }), isKwirthAvailable(entity) && !loading && validClusters && validClusters.length > 0 && validClusters.reduce((sum, cluster) => sum + cluster.pods.length, 0) > 0 && /* @__PURE__ */ React.createElement(Box, { sx: { display: "flex" } }, /* @__PURE__ */ React.createElement(Box, { sx: { width: "200px", maxWidth: "200px" } }, /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(ClusterList, { resources: validClusters, selectedClusterName, onSelect: onSelectCluster }))), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(Options, { metricsOptions: kwirthMetricsOptionsRef.current, selectedNamespaces, selectedPodNames, selectedContainerNames, onChange: onChangeOptions, disabled: selectedNamespaces.length === 0 || paused.current }))), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(KwirthNews, { latestVersions: backendInfo, backendVersion, ownVersion: VERSION }))))), /* @__PURE__ */ React.createElement(Box, { sx: { flexGrow: 1, p: 1, marginLeft: "8px" } }, !selectedClusterName && /* @__PURE__ */ React.createElement("img", { src: KwirthMetricsLogo, alt: "No cluster selected", style: { left: "40%", marginTop: "10%", width: "20%", position: "relative" } }), selectedClusterName && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Card, { style: { marginTop: -8 } }, /* @__PURE__ */ React.createElement(CardHeader, { title: statusButtons(selectedClusterName), style: { marginTop: -4, marginBottom: 4, flexShrink: 0 }, action: actionButtons() }), /* @__PURE__ */ React.createElement(Grid, { container: true, style: { alignItems: "end" } }, /* @__PURE__ */ React.createElement(Grid, { item: true, style: { width: "66%" } }, /* @__PURE__ */ React.createElement(Typography, { style: { marginLeft: 14 } }, /* @__PURE__ */ React.createElement(ObjectSelector, { cluster: validClusters.find((cluster) => cluster.name === selectedClusterName), onSelect: onSelectObject, disabled: selectedClusterName === "" || started || paused.current, selectedNamespaces, selectedPodNames, selectedContainerNames, scope: InstanceConfigScopeEnum.STREAM }))), /* @__PURE__ */ React.createElement(Grid, { item: true, style: { width: "33%", marginLeft: 0, marginBottom: 6, maxWidth: "33%" } }, /* @__PURE__ */ React.createElement(FormControl, { style: { width: "100%" } }, /* @__PURE__ */ React.createElement(Select, { value: selectedMetrics, MenuProps: { variant: "menu" }, multiple: true, onChange: onMetricsChange, renderValue: (selected) => selected.join(", ").substring(0, 40) + "...", disabled: selectedClusterName === "" || selectedNamespaces.length === 0 || started }, allMetrics.map(
|
|
541
|
+
(m) => /* @__PURE__ */ React.createElement(MenuItem, { key: m.metric, value: m.metric, style: { marginTop: "-8px", marginBottom: "-8px" } }, /* @__PURE__ */ React.createElement(Checkbox, { checked: selectedMetrics.includes(m.metric), style: { marginTop: "-8px", marginBottom: "-8px" } }), /* @__PURE__ */ React.createElement(Typography, { style: { marginTop: "-8px", marginBottom: "-8px" } }, m.metric))
|
|
542
|
+
))))), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(CardContent, { style: { overflow: "auto" } }, showMetrics(kwirthMetricsOptionsRef.current)))))), showStatusDialog && /* @__PURE__ */ React.createElement(StatusLog, { level: statusLevel, onClose: () => setShowStatusDialog(false), statusMessages, onClear: statusClear }));
|
|
523
543
|
};
|
|
524
544
|
|
|
525
545
|
export { EntityKwirthMetricsContent };
|