@jfvilas/plugin-kwirth-log 0.12.4 → 0.12.6
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 +19 -7
- package/dist/api/KwirthLogClient.esm.js +42 -30
- package/dist/api/KwirthLogClient.esm.js.map +1 -1
- package/dist/api/types.esm.js.map +1 -1
- package/dist/assets/kwirth-log-component-not-found.svg +3 -3
- package/dist/assets/kwirthlog-logo.svg +3 -3
- package/dist/components/EntityKwirthLogContent/EntityKwirthLogContent.esm.js +178 -67
- package/dist/components/EntityKwirthLogContent/EntityKwirthLogContent.esm.js.map +1 -1
- package/dist/components/ObjectSelector/ObjectSelector.esm.js +5 -5
- package/dist/components/ObjectSelector/ObjectSelector.esm.js.map +1 -1
- package/dist/components/StatusLog/StatusLog.esm.js +1 -1
- package/dist/components/StatusLog/StatusLog.esm.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/plugin.esm.js.map +1 -1
- package/package.json +1 -2
- package/dist/components/ShowError/ShowError.esm.js +0 -20
- package/dist/components/ShowError/ShowError.esm.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# Backstage frontend KwirthLog plugin
|
|
2
|
-
This package is a Backstage plugin for **viewing Kubernetes logs** in real-time (live-streaming) via Kwirth.
|
|
2
|
+
This package is a Backstage frontend plugin for **viewing Kubernetes logs** in real-time (live-streaming) via Kwirth.
|
|
3
3
|
|
|
4
|
-
**NOTE: KwithLog requires Kwirth vesrsion 0.3.
|
|
4
|
+
**NOTE: KwithLog requires Kwirth vesrsion 0.3.160 or greater**
|
|
5
5
|
|
|
6
|
-
This Backstage plugin allows you to live-stream Kubernetes logs associated to your Backstage entities directly inside your Backstage instance. It's very important to understand that for this plugin to work
|
|
6
|
+
This Backstage plugin allows you to live-stream Kubernetes logs associated to your Backstage entities directly inside your Backstage instance. It's very important to understand that for this plugin to work...:
|
|
7
|
+
|
|
8
|
+
- You need to install the Kwirth [Backstage backend plugin](https://www.npmjs.com/package/@jfvilas/plugin-kwirth-backend).
|
|
9
|
+
- You need to install Kwirth on your Kubernetes cluster, that is, this plugin is just another frontend for [Kwirth](https://jfvilas.github.io/kwirth).
|
|
7
10
|
|
|
8
11
|
Kwirth is a really-easy-to-use data-exporting system for Kubernetes that runs in only one pod (*no database is needed*). Refer to Kwirth GitHub project for [info on installation](https://github.com/jfvilas/kwirth?tab=readme-ov-file#installation). Kwirth installation is *one command away* from you.
|
|
9
12
|
|
|
@@ -11,7 +14,7 @@ You can access [Kwirth project here](https://github.com/jfvilas/kwirth).
|
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
## What is this plugin for?
|
|
14
|
-
This Backstage plugin adds Backstage a feature for viewing real-time Kubernetes logs of your Backstage entities directly inside Backstage frontend application. The plugin will be enabled for any entity that is
|
|
17
|
+
This Backstage plugin adds Backstage a feature for viewing real-time Kubernetes logs of your Backstage entities directly inside Backstage frontend application. The plugin will be enabled for any entity that is correctly tagged (according to Backstage Kubernetes core feature) and its correpsonding Kubernetes resources are found on any of the clusters that have been added to Backstage.
|
|
15
18
|
|
|
16
19
|
When KwirthLog is correctly installed and configured, it is possible to view Kubernetes logs on your Backstage like in this sample:
|
|
17
20
|
|
|
@@ -33,6 +36,15 @@ Let's explain this by following a user working sequence:
|
|
|
33
36
|
If everyting is correctly configured and tagged, the user should see a list of clusters. When selecting a cluster, the user should see a list of namespaces where the entity is running.
|
|
34
37
|
|
|
35
38
|
|
|
39
|
+
## Version compatibility
|
|
40
|
+
Following table shows version compatibility between this Kwirth Backstage plugin and Kwirth Core server.
|
|
41
|
+
|
|
42
|
+
| Plugin Kwirth version | Kwirth version |
|
|
43
|
+
|-|-|
|
|
44
|
+
|0.11.3|0.3.155|
|
|
45
|
+
|0.12.5|0.4.20|
|
|
46
|
+
|
|
47
|
+
|
|
36
48
|
## Installation
|
|
37
49
|
It's very simple and straightforward, it is in fact very similar to any other forntend Backstage plugin.
|
|
38
50
|
|
|
@@ -40,9 +52,9 @@ It's very simple and straightforward, it is in fact very similar to any other fo
|
|
|
40
52
|
|
|
41
53
|
2. Install this Backstage frontend plugin:
|
|
42
54
|
|
|
43
|
-
```
|
|
55
|
+
```sh
|
|
44
56
|
# From your Backstage root directory
|
|
45
|
-
yarn --cwd packages/app add @jfvilas/plugin-kwirth-log @jfvilas/plugin-kwirth-common
|
|
57
|
+
yarn --cwd packages/app add @jfvilas/plugin-kwirth-log @jfvilas/plugin-kwirth-common @jfvilas/kwirth-common
|
|
46
58
|
```
|
|
47
59
|
|
|
48
60
|
3. Make sure the [Kwirth backend plugin](https://www.npmjs.com/package/@jfvilas/plugin-kwirth-backend#configure) is installed and configured.
|
|
@@ -69,7 +81,7 @@ For Kwirth plugin to be usable on the frontend, you must tailor your Entity Page
|
|
|
69
81
|
<EntityLayout>
|
|
70
82
|
{/* other tabs... */}
|
|
71
83
|
<EntityLayout.Route if={isKwirthAvailable} path="/kwirthlog" title="KwirthLog">
|
|
72
|
-
<EntityKwirthLogContent />
|
|
84
|
+
<EntityKwirthLogContent enableRestart={false} />
|
|
73
85
|
</EntityLayout.Route>
|
|
74
86
|
</EntityLayout>
|
|
75
87
|
)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getVersion, requestAccess } from '@jfvilas/plugin-kwirth-common';
|
|
2
|
+
|
|
1
3
|
class KwirthLogClient {
|
|
2
4
|
discoveryApi;
|
|
3
5
|
fetchApi;
|
|
@@ -10,20 +12,25 @@ class KwirthLogClient {
|
|
|
10
12
|
* @param entity
|
|
11
13
|
* @returns an array of clusters (with their correpsonding info) and a pod list for each, where the entity has been dicovered
|
|
12
14
|
*/
|
|
15
|
+
// +++ test
|
|
13
16
|
async getVersion() {
|
|
14
|
-
|
|
15
|
-
const baseUrl = await this.discoveryApi.getBaseUrl("kwirth");
|
|
16
|
-
const targetUrl = `${baseUrl}/version`;
|
|
17
|
-
const result = await this.fetchApi.fetch(targetUrl);
|
|
18
|
-
const data = await result.json();
|
|
19
|
-
if (!result.ok) {
|
|
20
|
-
throw new Error(`getVersion error: not ok`);
|
|
21
|
-
}
|
|
22
|
-
return data.version;
|
|
23
|
-
} catch (err) {
|
|
24
|
-
throw new Error(`getVersion error: ${err}`);
|
|
25
|
-
}
|
|
17
|
+
return getVersion(this.discoveryApi, this.fetchApi);
|
|
26
18
|
}
|
|
19
|
+
// async getVersion(): Promise<string> {
|
|
20
|
+
// try {
|
|
21
|
+
// const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
|
|
22
|
+
// const targetUrl = `${baseUrl}/version`
|
|
23
|
+
// const result = await this.fetchApi.fetch(targetUrl)
|
|
24
|
+
// const data = await result.json()
|
|
25
|
+
// if (!result.ok) {
|
|
26
|
+
// throw new Error(`getVersion error: not ok`)
|
|
27
|
+
// }
|
|
28
|
+
// return data.version
|
|
29
|
+
// }
|
|
30
|
+
// catch (err) {
|
|
31
|
+
// throw new Error(`getVersion error: ${err}`)
|
|
32
|
+
// }
|
|
33
|
+
// }
|
|
27
34
|
async getResources(entity) {
|
|
28
35
|
try {
|
|
29
36
|
const baseUrl = await this.discoveryApi.getBaseUrl("kwirth");
|
|
@@ -40,25 +47,30 @@ class KwirthLogClient {
|
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
49
|
async requestAccess(entity, channel, scopes) {
|
|
43
|
-
|
|
44
|
-
const baseUrl = await this.discoveryApi.getBaseUrl("kwirth");
|
|
45
|
-
var targetUrl = new URL(`${baseUrl}/access`);
|
|
46
|
-
targetUrl.searchParams.append("scopes", scopes.join(","));
|
|
47
|
-
targetUrl.searchParams.append("channel", channel);
|
|
48
|
-
var payload = JSON.stringify(entity);
|
|
49
|
-
const result = await this.fetchApi.fetch(targetUrl, { method: "POST", body: payload, headers: { "Content-Type": "application/json" } });
|
|
50
|
-
const data = await result.json();
|
|
51
|
-
for (var c of data) {
|
|
52
|
-
c.accessKeys = new Map(JSON.parse(c.accessKeys));
|
|
53
|
-
}
|
|
54
|
-
if (!result.ok) {
|
|
55
|
-
throw new Error(`requestAccess error: not ok`);
|
|
56
|
-
}
|
|
57
|
-
return data;
|
|
58
|
-
} catch (err) {
|
|
59
|
-
throw new Error(`requestAccess error: ${err}`);
|
|
60
|
-
}
|
|
50
|
+
return requestAccess(this.discoveryApi, this.fetchApi, entity, channel, scopes);
|
|
61
51
|
}
|
|
52
|
+
// async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {
|
|
53
|
+
// try {
|
|
54
|
+
// const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
|
|
55
|
+
// var targetUrl:URL= new URL (`${baseUrl}/access`)
|
|
56
|
+
// targetUrl.searchParams.append('scopes',scopes.join(','))
|
|
57
|
+
// targetUrl.searchParams.append('channel',channel)
|
|
58
|
+
// var payload=JSON.stringify(entity)
|
|
59
|
+
// const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})
|
|
60
|
+
// const data = await result.json() as ClusterValidPods[]
|
|
61
|
+
// // we reconstruct the 'Map' from string of arrays
|
|
62
|
+
// for (var c of data) {
|
|
63
|
+
// c.accessKeys = new Map(JSON.parse(((c as any).accessKeys)))
|
|
64
|
+
// }
|
|
65
|
+
// if (!result.ok) {
|
|
66
|
+
// throw new Error(`requestAccess error: not ok`)
|
|
67
|
+
// }
|
|
68
|
+
// return data
|
|
69
|
+
// }
|
|
70
|
+
// catch (err) {
|
|
71
|
+
// throw new Error(`requestAccess error: ${err}`)
|
|
72
|
+
// }
|
|
73
|
+
// }
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
export { KwirthLogClient };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KwirthLogClient.esm.js","sources":["../../src/api/KwirthLogClient.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 { KwirthLogApi } from './types'\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\n\r\nexport interface KwirthLogClientOptions {\r\n discoveryApi: DiscoveryApi\r\n fetchApi: FetchApi\r\n}\r\n\r\nexport class KwirthLogClient implements KwirthLogApi {\r\n private readonly discoveryApi: DiscoveryApi\r\n private readonly fetchApi: FetchApi\r\n\r\n constructor(options: KwirthLogClientOptions) {\r\n this.discoveryApi = options.discoveryApi\r\n this.fetchApi = options.fetchApi\r\n }\r\n\r\n /**\r\n * \r\n * @param entity \r\n * @returns an array of clusters (with their correpsonding info) and a pod list for each, where the entity has been dicovered\r\n */\r\n async getVersion(): Promise<string> {\r\n try {\r\n
|
|
1
|
+
{"version":3,"file":"KwirthLogClient.esm.js","sources":["../../src/api/KwirthLogClient.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 { KwirthLogApi } from './types'\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { ClusterValidPods, getVersion, requestAccess } from '@jfvilas/plugin-kwirth-common'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\n\r\nexport interface KwirthLogClientOptions {\r\n discoveryApi: DiscoveryApi\r\n fetchApi: FetchApi\r\n}\r\n\r\nexport class KwirthLogClient implements KwirthLogApi {\r\n private readonly discoveryApi: DiscoveryApi\r\n private readonly fetchApi: FetchApi\r\n\r\n constructor(options: KwirthLogClientOptions) {\r\n this.discoveryApi = options.discoveryApi\r\n this.fetchApi = options.fetchApi\r\n }\r\n\r\n /**\r\n * \r\n * @param entity \r\n * @returns an array of clusters (with their correpsonding info) and a pod list for each, where the entity has been dicovered\r\n */\r\n // +++ test\r\n async getVersion() : Promise<string> {\r\n return getVersion(this.discoveryApi, this.fetchApi)\r\n }\r\n // async getVersion(): Promise<string> {\r\n // try {\r\n // const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n // const targetUrl = `${baseUrl}/version`\r\n\r\n // const result = await this.fetchApi.fetch(targetUrl)\r\n // const data = await result.json()\r\n\r\n // if (!result.ok) {\r\n // throw new Error(`getVersion error: not ok`)\r\n // }\r\n // return data.version\r\n // }\r\n // catch (err) {\r\n // throw new Error(`getVersion error: ${err}`)\r\n // }\r\n // }\r\n\r\n async getResources(entity:Entity): Promise<ClusterValidPods> {\r\n try {\r\n const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n const targetUrl = `${baseUrl}/start`\r\n\r\n var payload=JSON.stringify(entity)\r\n const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})\r\n const data = await result.json() as ClusterValidPods\r\n\r\n if (!result.ok) {\r\n throw new Error(`getResources error: not ok`)\r\n }\r\n return data\r\n }\r\n catch (err) {\r\n throw new Error(`getResources error: ${err}`)\r\n }\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 // async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {\r\n // try {\r\n // const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n // var targetUrl:URL= new URL (`${baseUrl}/access`)\r\n // targetUrl.searchParams.append('scopes',scopes.join(','))\r\n // targetUrl.searchParams.append('channel',channel)\r\n\r\n // var payload=JSON.stringify(entity)\r\n // const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})\r\n // const data = await result.json() as ClusterValidPods[]\r\n\r\n // // we reconstruct the 'Map' from string of arrays\r\n // for (var c of data) {\r\n // c.accessKeys = new Map(JSON.parse(((c as any).accessKeys)))\r\n // }\r\n // if (!result.ok) {\r\n // throw new Error(`requestAccess error: not ok`)\r\n // }\r\n // return data\r\n // }\r\n // catch (err) {\r\n // throw new Error(`requestAccess error: ${err}`)\r\n // }\r\n // }\r\n\r\n}\r\n"],"names":[],"mappings":";;AA0BO,MAAM,eAAwC,CAAA;AAAA,EAChC,YAAA;AAAA,EACA,QAAA;AAAA,EAEjB,YAAY,OAAiC,EAAA;AACzC,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAQ,CAAA,QAAA;AAAA;AAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAA+B,GAAA;AACjC,IAAA,OAAO,UAAW,CAAA,IAAA,CAAK,YAAc,EAAA,IAAA,CAAK,QAAQ,CAAA;AAAA;AACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,aAAa,MAA0C,EAAA;AACzD,IAAI,IAAA;AACA,MAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,QAAQ,CAAA;AAC3D,MAAM,MAAA,SAAA,GAAY,GAAG,OAAO,CAAA,MAAA,CAAA;AAE5B,MAAI,IAAA,OAAA,GAAQ,IAAK,CAAA,SAAA,CAAU,MAAM,CAAA;AACjC,MAAA,MAAM,SAAS,MAAM,IAAA,CAAK,QAAS,CAAA,KAAA,CAAM,WAAW,EAAC,MAAA,EAAO,MAAQ,EAAA,IAAA,EAAK,SAAS,OAAQ,EAAA,EAAC,cAAe,EAAA,kBAAA,IAAoB,CAAA;AAC9H,MAAM,MAAA,IAAA,GAAO,MAAM,MAAA,CAAO,IAAK,EAAA;AAE/B,MAAI,IAAA,CAAC,OAAO,EAAI,EAAA;AACZ,QAAM,MAAA,IAAI,MAAM,CAA4B,0BAAA,CAAA,CAAA;AAAA;AAEhD,MAAO,OAAA,IAAA;AAAA,aAEJ,GAAK,EAAA;AACR,MAAA,MAAM,IAAI,KAAA,CAAM,CAAuB,oBAAA,EAAA,GAAG,CAAE,CAAA,CAAA;AAAA;AAChD;AACJ,EAEA,MAAM,aAAA,CAAc,MAAe,EAAA,OAAA,EAAgB,MAA+D,EAAA;AAC9G,IAAA,OAAO,cAAc,IAAK,CAAA,YAAA,EAAc,KAAK,QAAU,EAAA,MAAA,EAAQ,SAAS,MAAM,CAAA;AAAA;AAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BJ;;;;"}
|
|
@@ -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 KwirthLogApi {\r\n getResources(entity:Entity): Promise<any>\r\n
|
|
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 KwirthLogApi {\r\n getResources(entity:Entity): Promise<any>\r\n requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]>\r\n getVersion(): Promise<any>\r\n}\r\n\r\nexport const kwirthLogApiRef = createApiRef<KwirthLogApi>({\r\n id: 'plugin.kwirthlog.api',\r\n})\r\n"],"names":[],"mappings":";;AA0BO,MAAM,kBAAkB,YAA2B,CAAA;AAAA,EACxD,EAAI,EAAA;AACN,CAAC;;;;"}
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<rect style="fill-rule: nonzero; stroke: rgb(255, 255, 255); stroke-width: 0px; fill: rgb(230, 230, 230); transform-origin: 228.554px 205.227px;" transform="matrix(0.985765, -0.168131, 0.16314, 0.986616, -50.714188, -2.839044)" x="101.002" y="192.327" width="255.103" height="25.801" rx="12.015" ry="12.015"></rect>
|
|
12
12
|
<rect style="fill-rule: nonzero; stroke: rgb(255, 255, 255); stroke-width: 0px; fill: rgb(230, 230, 230); transform-origin: 231.862px 205.227px;" transform="matrix(0.985765, -0.168131, 0.16314, 0.986616, -73.522724, -49.884953)" x="102.464" y="192.327" width="258.794" height="25.801" rx="12.015" ry="12.015"></rect>
|
|
13
13
|
<path style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: medium; line-height: normal; font-family: sans-serif; font-feature-settings: normal; text-indent: 0px; text-align: start; text-decoration: none solid rgb(0, 0, 0); letter-spacing: normal; word-spacing: normal; text-transform: none; writing-mode: lr-tb; direction: ltr; text-orientation: mixed; dominant-baseline: auto; baseline-shift: baseline; text-anchor: start; white-space: normal; clip-rule: nonzero; display: inline; overflow: visible; visibility: visible; opacity: 1; isolation: auto; mix-blend-mode: normal; color-interpolation: srgb; color-interpolation-filters: linearrgb; vector-effect: none; fill: rgb(255, 255, 255); fill-opacity: 1; fill-rule: evenodd; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0; stroke-opacity: 1; color-rendering: auto; image-rendering: auto; shape-rendering: auto; text-rendering: auto; paint-order: fill; stroke-width: 9px; stroke: rgb(74, 74, 74);" d="M 90.279 31.639 L 236.352 31.639 L 236.352 225.458 L 90.279 225.458 L 90.279 31.639 Z" id="path3310"></path>
|
|
14
|
-
<g id="g3330" transform="matrix(0.
|
|
15
|
-
<g transform="matrix(6.103682, 0, 0, 5.
|
|
14
|
+
<g id="g3330" transform="matrix(0.417521, 0, 0, 0.461789, -751.809143, -5115.862305)" style="">
|
|
15
|
+
<g transform="matrix(6.103682, 0, 0, 5.605206, 1904.565796, 10976.322266)" style="">
|
|
16
16
|
<g>
|
|
17
17
|
<path d="M 68.066 63.636 L 25.648 63.636 C 25.096 63.636 24.648 63.189 24.648 62.636 C 24.648 62.083 25.096 61.636 25.648 61.636 L 68.066 61.636 C 68.619 61.636 69.066 62.083 69.066 62.636 C 69.066 63.189 68.619 63.636 68.066 63.636 Z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; fill: rgb(156, 156, 156);" stroke-linecap="round"></path>
|
|
18
18
|
<path d="M 54.048 57.677 L 25.325 57.677 C 24.951 57.677 24.648 57.23 24.648 56.677 C 24.648 56.124 24.951 55.677 25.325 55.677 L 54.048 55.677 C 54.422 55.677 54.725 56.124 54.725 56.677 C 54.725 57.23 54.422 57.677 54.048 57.677 Z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; fill: rgb(156, 156, 156);" stroke-linecap="round"></path>
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
</g>
|
|
27
27
|
</g>
|
|
28
28
|
</g>
|
|
29
|
-
<text style="fill: rgb(74, 74, 74); font-family: Consolas; font-size: 34px; font-weight: 700; stroke-miterlimit: 10; stroke-width: 0px; white-space: pre;" transform="matrix(0.654152, 0, 0, 0.636825,
|
|
29
|
+
<text style="fill: rgb(74, 74, 74); font-family: Consolas; font-size: 34px; font-weight: 700; stroke-miterlimit: 10; stroke-width: 0px; white-space: pre;" transform="matrix(0.654152, 0, 0, 0.636825, 31.813269, 80.181999)" x="114.293" y="147.365">KwirthLog</text>
|
|
30
30
|
</svg>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<svg viewBox="0 0 152 200" xmlns="http://www.w3.org/2000/svg" xmlns:bx="https://boxy-svg.com">
|
|
2
2
|
<path style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: medium; line-height: normal; font-family: sans-serif; font-feature-settings: normal; text-indent: 0px; text-align: start; text-decoration: none solid rgb(0, 0, 0); letter-spacing: normal; word-spacing: normal; text-transform: none; writing-mode: lr-tb; direction: ltr; text-orientation: mixed; dominant-baseline: auto; baseline-shift: baseline; text-anchor: start; white-space: normal; clip-rule: nonzero; display: inline; overflow: visible; visibility: visible; opacity: 1; isolation: auto; mix-blend-mode: normal; color-interpolation: srgb; color-interpolation-filters: linearrgb; vector-effect: none; fill: rgb(255, 255, 255); fill-opacity: 1; fill-rule: evenodd; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0; stroke-opacity: 1; color-rendering: auto; image-rendering: auto; shape-rendering: auto; text-rendering: auto; paint-order: fill; stroke-width: 9px; stroke: rgb(74, 74, 74);" d="M 3.001 3.226 L 149.074 3.226 L 149.074 197.045 L 3.001 197.045 L 3.001 3.226 Z" id="path3310"></path>
|
|
3
|
-
<g id="g3330" transform="matrix(0.
|
|
4
|
-
<g transform="matrix(6.103682, 0, 0, 5.
|
|
3
|
+
<g id="g3330" transform="matrix(0.417521, 0, 0, 0.461789, -838.360535, -5144.637207)" style="">
|
|
4
|
+
<g transform="matrix(6.103682, 0, 0, 5.605206, 1904.565796, 10976.322266)" style="">
|
|
5
5
|
<g>
|
|
6
6
|
<path d="M 68.066 63.636 L 25.648 63.636 C 25.096 63.636 24.648 63.189 24.648 62.636 C 24.648 62.083 25.096 61.636 25.648 61.636 L 68.066 61.636 C 68.619 61.636 69.066 62.083 69.066 62.636 C 69.066 63.189 68.619 63.636 68.066 63.636 Z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; fill: rgb(156, 156, 156);" stroke-linecap="round"></path>
|
|
7
7
|
<path d="M 54.048 57.677 L 25.325 57.677 C 24.951 57.677 24.648 57.23 24.648 56.677 C 24.648 56.124 24.951 55.677 25.325 55.677 L 54.048 55.677 C 54.422 55.677 54.725 56.124 54.725 56.677 C 54.725 57.23 54.422 57.677 54.048 57.677 Z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; fill: rgb(156, 156, 156);" stroke-linecap="round"></path>
|
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
</g>
|
|
16
16
|
</g>
|
|
17
17
|
</g>
|
|
18
|
-
<text style="fill: rgb(74, 74, 74); font-family: Consolas; font-size: 34px; font-weight: 700; stroke-miterlimit: 10; stroke-width: 0px; white-space: pre;" transform="matrix(0.654152, 0, 0, 0.636825, -
|
|
18
|
+
<text style="fill: rgb(74, 74, 74); font-family: Consolas; font-size: 34px; font-weight: 700; stroke-miterlimit: 10; stroke-width: 0px; white-space: pre;" transform="matrix(0.654152, 0, 0, 0.636825, -53.705204, 51.365246)" x="114.293" y="147.365">KwirthLog</text>
|
|
19
19
|
</svg>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
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
|
-
import { useApi } from '@backstage/core-plugin-api';
|
|
4
|
+
import { useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
5
5
|
import { isKwirthAvailable, ANNOTATION_KWIRTH_LOCATION } from '@jfvilas/plugin-kwirth-common';
|
|
6
6
|
import { useEntity, MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react';
|
|
7
7
|
import { kwirthLogApiRef } from '../../api/types.esm.js';
|
|
8
|
-
import { SignalMessageLevelEnum, InstanceConfigScopeEnum,
|
|
8
|
+
import { SignalMessageLevelEnum, InstanceConfigScopeEnum, InstanceMessageChannelEnum, InstanceMessageTypeEnum, OpsCommandEnum, accessKeySerialize, InstanceMessageFlowEnum, InstanceMessageActionEnum, InstanceConfigViewEnum, InstanceConfigObjectEnum } from '@jfvilas/kwirth-common';
|
|
9
9
|
import { ComponentNotFound, ErrorType } from '../ComponentNotFound/ComponentNotFound.esm.js';
|
|
10
|
+
import { ObjectSelector } from '../ObjectSelector/ObjectSelector.esm.js';
|
|
10
11
|
import { Options } from '../Options/Options.esm.js';
|
|
11
12
|
import { ClusterList } from '../ClusterList/ClusterList.esm.js';
|
|
12
|
-
import { ShowError } from '../ShowError/ShowError.esm.js';
|
|
13
13
|
import { StatusLog } from '../StatusLog/StatusLog.esm.js';
|
|
14
|
-
import { Grid, Card, CardHeader, CardContent } from '@material-ui/core';
|
|
14
|
+
import { Box, Grid, Card, CardHeader, CardContent } from '@material-ui/core';
|
|
15
15
|
import Divider from '@material-ui/core/Divider';
|
|
16
16
|
import IconButton from '@material-ui/core/IconButton';
|
|
17
17
|
import Typography from '@material-ui/core/Typography';
|
|
@@ -23,19 +23,18 @@ import WarningIcon from '@material-ui/icons/Warning';
|
|
|
23
23
|
import ErrorIcon from '@material-ui/icons/Error';
|
|
24
24
|
import DownloadIcon from '@material-ui/icons/CloudDownload';
|
|
25
25
|
import KwirthLogLogo from '../../assets/kwirthlog-logo.svg';
|
|
26
|
-
import
|
|
26
|
+
import RefreshIcon from '@material-ui/icons/Refresh';
|
|
27
27
|
|
|
28
28
|
const LOG_MAX_MESSAGES = 1e3;
|
|
29
|
-
const EntityKwirthLogContent = () => {
|
|
29
|
+
const EntityKwirthLogContent = (props) => {
|
|
30
30
|
const { entity } = useEntity();
|
|
31
31
|
const kwirthLogApi = useApi(kwirthLogApiRef);
|
|
32
|
+
const alertApi = useApi(alertApiRef);
|
|
32
33
|
const [resources, setResources] = useState([]);
|
|
33
34
|
const [selectedClusterName, setSelectedClusterName] = useState("");
|
|
34
|
-
const [_namespaceList, setNamespaceList] = useState([]);
|
|
35
35
|
const [selectedNamespaces, setSelectedNamespaces] = useState([]);
|
|
36
36
|
const [selectedPodNames, setSelectedPodNames] = useState([]);
|
|
37
37
|
const [selectedContainerNames, setSelectedContainerNames] = useState([]);
|
|
38
|
-
const [showError, setShowError] = useState("");
|
|
39
38
|
const [started, setStarted] = useState(false);
|
|
40
39
|
const [stopped, setStopped] = useState(true);
|
|
41
40
|
const paused = useRef(false);
|
|
@@ -43,6 +42,7 @@ const EntityKwirthLogContent = () => {
|
|
|
43
42
|
const [pendingMessages, setPendingMessages] = useState([]);
|
|
44
43
|
const [statusMessages, setStatusMessages] = useState([]);
|
|
45
44
|
const [websocket, setWebsocket] = useState();
|
|
45
|
+
const [instance, setInstance] = useState();
|
|
46
46
|
const kwirthLogOptionsRef = useRef({ timestamp: false, follow: true, fromStart: false });
|
|
47
47
|
const [showStatusDialog, setShowStatusDialog] = useState(false);
|
|
48
48
|
const [statusLevel, setStatusLevel] = useState(SignalMessageLevelEnum.INFO);
|
|
@@ -51,9 +51,12 @@ const EntityKwirthLogContent = () => {
|
|
|
51
51
|
const [backendVersion, setBackendVersion] = useState("");
|
|
52
52
|
const { loading, error } = useAsync(async () => {
|
|
53
53
|
if (backendVersion === "") setBackendVersion(await kwirthLogApi.getVersion());
|
|
54
|
-
|
|
54
|
+
let reqScopes = [InstanceConfigScopeEnum.VIEW];
|
|
55
|
+
if (props.enableRestart) reqScopes.push(InstanceConfigScopeEnum.RESTART);
|
|
56
|
+
let data = await kwirthLogApi.requestAccess(entity, InstanceMessageChannelEnum.LOG, reqScopes);
|
|
55
57
|
setResources(data);
|
|
56
58
|
});
|
|
59
|
+
const buffer = useRef(/* @__PURE__ */ new Map());
|
|
57
60
|
const clickStart = (options) => {
|
|
58
61
|
if (!paused.current) {
|
|
59
62
|
setStarted(true);
|
|
@@ -67,11 +70,11 @@ const EntityKwirthLogContent = () => {
|
|
|
67
70
|
setStarted(true);
|
|
68
71
|
}
|
|
69
72
|
};
|
|
70
|
-
const
|
|
73
|
+
const onClickPause = () => {
|
|
71
74
|
setStarted(false);
|
|
72
75
|
paused.current = true;
|
|
73
76
|
};
|
|
74
|
-
const
|
|
77
|
+
const onClickStop = () => {
|
|
75
78
|
setStarted(false);
|
|
76
79
|
setStopped(true);
|
|
77
80
|
paused.current = false;
|
|
@@ -80,57 +83,99 @@ const EntityKwirthLogContent = () => {
|
|
|
80
83
|
const onSelectCluster = (name) => {
|
|
81
84
|
if (name) {
|
|
82
85
|
setSelectedClusterName(name);
|
|
83
|
-
resources.filter((cluster) => cluster.name === name).map((x) => {
|
|
84
|
-
var namespaces = Array.from(new Set(x.data.map((p) => p.namespace)));
|
|
85
|
-
setNamespaceList(namespaces);
|
|
86
|
-
});
|
|
87
86
|
setMessages([{
|
|
88
|
-
channel: InstanceConfigChannelEnum.LOG,
|
|
89
87
|
type: InstanceMessageTypeEnum.SIGNAL,
|
|
90
88
|
text: "Select namespace in order to decide which pod logs to view.",
|
|
91
|
-
|
|
89
|
+
namespace: "",
|
|
90
|
+
pod: "",
|
|
91
|
+
container: ""
|
|
92
92
|
}]);
|
|
93
93
|
setSelectedNamespaces([]);
|
|
94
94
|
setSelectedPodNames([]);
|
|
95
95
|
setSelectedContainerNames([]);
|
|
96
96
|
setStatusMessages([]);
|
|
97
|
-
|
|
97
|
+
onClickStop();
|
|
98
98
|
}
|
|
99
99
|
};
|
|
100
100
|
const processLogMessage = (wsEvent) => {
|
|
101
|
-
let
|
|
102
|
-
switch (
|
|
103
|
-
case
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
101
|
+
let instanceMessage = JSON.parse(wsEvent.data);
|
|
102
|
+
switch (instanceMessage.type) {
|
|
103
|
+
case InstanceMessageTypeEnum.DATA:
|
|
104
|
+
let logMessage = instanceMessage;
|
|
105
|
+
let bname = logMessage.namespace + "/" + logMessage.pod + "/" + logMessage.container;
|
|
106
|
+
let text = logMessage.text;
|
|
107
|
+
if (!buffer.current.has(bname)) buffer.current.set(bname, "");
|
|
108
|
+
if (buffer.current.get(bname)) {
|
|
109
|
+
text = buffer.current.get(bname) + text;
|
|
110
|
+
buffer.current.set(bname, "");
|
|
111
|
+
}
|
|
112
|
+
if (!text.endsWith("\n")) {
|
|
113
|
+
let i = text.lastIndexOf("\n");
|
|
114
|
+
buffer.current.set(bname, text.substring(i));
|
|
115
|
+
text = text.substring(0, i);
|
|
116
|
+
}
|
|
117
|
+
for (let line of text.split("\n")) {
|
|
118
|
+
if (line.trim() === "") continue;
|
|
119
|
+
let logLine = {
|
|
120
|
+
text: line,
|
|
121
|
+
namespace: logMessage.namespace,
|
|
122
|
+
pod: logMessage.pod,
|
|
123
|
+
container: logMessage.container,
|
|
124
|
+
type: logMessage.type
|
|
125
|
+
};
|
|
126
|
+
if (paused.current) {
|
|
127
|
+
setPendingMessages((prev) => [...prev, logLine]);
|
|
128
|
+
} else {
|
|
129
|
+
setMessages((prev) => {
|
|
130
|
+
while (prev.length > LOG_MAX_MESSAGES - 1) {
|
|
131
|
+
prev.splice(0, 1);
|
|
132
|
+
}
|
|
133
|
+
if (kwirthLogOptionsRef.current.follow && lastRef.current) lastRef.current.scrollIntoView({ behavior: "instant", block: "start" });
|
|
134
|
+
return [...prev, logLine];
|
|
135
|
+
});
|
|
136
|
+
}
|
|
115
137
|
}
|
|
116
138
|
break;
|
|
117
|
-
case
|
|
118
|
-
|
|
119
|
-
|
|
139
|
+
case InstanceMessageTypeEnum.SIGNAL:
|
|
140
|
+
if (instanceMessage.flow === InstanceMessageFlowEnum.RESPONSE && instanceMessage.action === InstanceMessageActionEnum.START) {
|
|
141
|
+
if (instanceMessage.instance !== "")
|
|
142
|
+
setInstance(instanceMessage.instance);
|
|
143
|
+
else {
|
|
144
|
+
let signalMessage = instanceMessage;
|
|
145
|
+
alertApi.post({ message: signalMessage.text, severity: "error", display: "transient" });
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
let signalMessage = instanceMessage;
|
|
149
|
+
addMessage(signalMessage.level, signalMessage.text);
|
|
150
|
+
switch (signalMessage.level) {
|
|
151
|
+
case SignalMessageLevelEnum.INFO:
|
|
152
|
+
alertApi.post({ message: signalMessage.text, severity: "info", display: "transient" });
|
|
153
|
+
break;
|
|
154
|
+
case SignalMessageLevelEnum.WARNING:
|
|
155
|
+
alertApi.post({ message: signalMessage.text, severity: "warning", display: "transient" });
|
|
156
|
+
break;
|
|
157
|
+
case SignalMessageLevelEnum.ERROR:
|
|
158
|
+
alertApi.post({ message: signalMessage.text, severity: "error", display: "transient" });
|
|
159
|
+
break;
|
|
160
|
+
default:
|
|
161
|
+
alertApi.post({ message: signalMessage.text, severity: "success", display: "transient" });
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
120
165
|
break;
|
|
121
166
|
default:
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
setStatusMessages((prev) => [...prev, {
|
|
125
|
-
channel: InstanceConfigChannelEnum.LOG,
|
|
126
|
-
type: InstanceMessageTypeEnum.SIGNAL,
|
|
127
|
-
level: SignalMessageLevelEnum.ERROR,
|
|
128
|
-
text: "Invalid message type received: " + msg.type,
|
|
129
|
-
instance: ""
|
|
130
|
-
}]);
|
|
167
|
+
addMessage(SignalMessageLevelEnum.ERROR, "Invalid message type received: " + instanceMessage.type);
|
|
168
|
+
alertApi.post({ message: "Invalid message type received: " + instanceMessage.type, severity: "error", display: "transient" });
|
|
131
169
|
break;
|
|
132
170
|
}
|
|
133
171
|
};
|
|
172
|
+
const addMessage = (level, text) => {
|
|
173
|
+
setStatusMessages((prev) => [...prev, {
|
|
174
|
+
level,
|
|
175
|
+
text,
|
|
176
|
+
type: InstanceMessageTypeEnum.SIGNAL
|
|
177
|
+
}]);
|
|
178
|
+
};
|
|
134
179
|
const websocketOnMessage = (wsEvent) => {
|
|
135
180
|
let instanceMessage;
|
|
136
181
|
try {
|
|
@@ -141,21 +186,31 @@ const EntityKwirthLogContent = () => {
|
|
|
141
186
|
return;
|
|
142
187
|
}
|
|
143
188
|
switch (instanceMessage.channel) {
|
|
144
|
-
case
|
|
189
|
+
case InstanceMessageChannelEnum.LOG:
|
|
145
190
|
processLogMessage(wsEvent);
|
|
146
191
|
break;
|
|
192
|
+
case InstanceMessageChannelEnum.OPS:
|
|
193
|
+
let opsMessage = instanceMessage;
|
|
194
|
+
if (opsMessage.data?.data)
|
|
195
|
+
addMessage(SignalMessageLevelEnum.WARNING, "Operations message: " + opsMessage.data.data);
|
|
196
|
+
else
|
|
197
|
+
addMessage(SignalMessageLevelEnum.WARNING, "Operations message: " + JSON.stringify(opsMessage));
|
|
198
|
+
break;
|
|
147
199
|
default:
|
|
148
|
-
|
|
200
|
+
addMessage(SignalMessageLevelEnum.ERROR, "Invalid channel in message: " + instanceMessage.channel);
|
|
201
|
+
addMessage(SignalMessageLevelEnum.ERROR, "Invalid message: " + JSON.stringify(instanceMessage));
|
|
149
202
|
break;
|
|
150
203
|
}
|
|
151
204
|
};
|
|
152
205
|
const websocketOnOpen = (ws, options) => {
|
|
153
206
|
let cluster = resources.find((cluster2) => cluster2.name === selectedClusterName);
|
|
154
207
|
if (!cluster) {
|
|
208
|
+
addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
|
|
155
209
|
return;
|
|
156
210
|
}
|
|
157
211
|
let pods = cluster.data.filter((p2) => selectedNamespaces.includes(p2.namespace));
|
|
158
212
|
if (!pods) {
|
|
213
|
+
addMessage(SignalMessageLevelEnum.ERROR, "No pods found");
|
|
159
214
|
return;
|
|
160
215
|
}
|
|
161
216
|
console.log(`WS connected`);
|
|
@@ -170,10 +225,10 @@ const EntityKwirthLogContent = () => {
|
|
|
170
225
|
}
|
|
171
226
|
}
|
|
172
227
|
let iConfig = {
|
|
173
|
-
channel:
|
|
228
|
+
channel: InstanceMessageChannelEnum.LOG,
|
|
174
229
|
objects: InstanceConfigObjectEnum.PODS,
|
|
175
|
-
action:
|
|
176
|
-
flow:
|
|
230
|
+
action: InstanceMessageActionEnum.START,
|
|
231
|
+
flow: InstanceMessageFlowEnum.REQUEST,
|
|
177
232
|
instance: "",
|
|
178
233
|
accessKey: accessKeySerialize(accessKey),
|
|
179
234
|
scope: InstanceConfigScopeEnum.VIEW,
|
|
@@ -187,14 +242,19 @@ const EntityKwirthLogContent = () => {
|
|
|
187
242
|
previous: false,
|
|
188
243
|
maxMessages: LOG_MAX_MESSAGES,
|
|
189
244
|
fromStart: options.fromStart
|
|
190
|
-
}
|
|
245
|
+
},
|
|
246
|
+
type: InstanceMessageTypeEnum.SIGNAL
|
|
191
247
|
};
|
|
192
248
|
ws.send(JSON.stringify(iConfig));
|
|
249
|
+
} else {
|
|
250
|
+
addMessage(SignalMessageLevelEnum.ERROR, "No accessKey for starting log streaming");
|
|
251
|
+
return;
|
|
193
252
|
}
|
|
194
253
|
};
|
|
195
254
|
const startLogViewer = (options) => {
|
|
196
255
|
let cluster = resources.find((cluster2) => cluster2.name === selectedClusterName);
|
|
197
256
|
if (!cluster) {
|
|
257
|
+
addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
|
|
198
258
|
return;
|
|
199
259
|
}
|
|
200
260
|
setMessages([]);
|
|
@@ -206,10 +266,11 @@ const EntityKwirthLogContent = () => {
|
|
|
206
266
|
setWebsocket(ws);
|
|
207
267
|
} catch (err) {
|
|
208
268
|
setMessages([{
|
|
209
|
-
channel: InstanceConfigChannelEnum.LOG,
|
|
210
269
|
type: InstanceMessageTypeEnum.DATA,
|
|
211
270
|
text: `Error opening log stream: ${err}`,
|
|
212
|
-
|
|
271
|
+
namespace: "",
|
|
272
|
+
pod: "",
|
|
273
|
+
container: ""
|
|
213
274
|
}]);
|
|
214
275
|
}
|
|
215
276
|
};
|
|
@@ -221,10 +282,11 @@ const EntityKwirthLogContent = () => {
|
|
|
221
282
|
};
|
|
222
283
|
const stopLogViewer = () => {
|
|
223
284
|
messages.push({
|
|
224
|
-
channel: InstanceConfigChannelEnum.LOG,
|
|
225
285
|
type: InstanceMessageTypeEnum.DATA,
|
|
226
286
|
text: "============================================================================================================================",
|
|
227
|
-
|
|
287
|
+
namespace: "",
|
|
288
|
+
pod: "",
|
|
289
|
+
container: ""
|
|
228
290
|
});
|
|
229
291
|
websocket?.close();
|
|
230
292
|
};
|
|
@@ -234,7 +296,7 @@ const EntityKwirthLogContent = () => {
|
|
|
234
296
|
clickStart(options);
|
|
235
297
|
}
|
|
236
298
|
};
|
|
237
|
-
const
|
|
299
|
+
const onClickDownload = () => {
|
|
238
300
|
let content = preRef.current.innerHTML.replaceAll("<pre>", "").replaceAll("</pre>", "\n");
|
|
239
301
|
content = content.replaceAll('<span style="color: green;">', "");
|
|
240
302
|
content = content.replaceAll('<span style="color: blue;">', "");
|
|
@@ -251,18 +313,67 @@ const EntityKwirthLogContent = () => {
|
|
|
251
313
|
document.body.removeChild(link);
|
|
252
314
|
URL.revokeObjectURL(url);
|
|
253
315
|
};
|
|
316
|
+
const onClickRestart = () => {
|
|
317
|
+
var cluster = resources.find((cluster2) => cluster2.name === selectedClusterName);
|
|
318
|
+
if (!cluster) {
|
|
319
|
+
addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
let restartKey = cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART);
|
|
323
|
+
if (!restartKey) {
|
|
324
|
+
addMessage(SignalMessageLevelEnum.ERROR, "No access key present");
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if (!instance) {
|
|
328
|
+
addMessage(SignalMessageLevelEnum.ERROR, "No instance has been established");
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
let pods = cluster.data.filter((pod) => selectedNamespaces.includes(pod.namespace));
|
|
332
|
+
for (let pod of pods) {
|
|
333
|
+
let opsMessage = {
|
|
334
|
+
msgtype: "opsmessage",
|
|
335
|
+
action: InstanceMessageActionEnum.COMMAND,
|
|
336
|
+
flow: InstanceMessageFlowEnum.IMMEDIATE,
|
|
337
|
+
type: InstanceMessageTypeEnum.DATA,
|
|
338
|
+
channel: InstanceMessageChannelEnum.OPS,
|
|
339
|
+
instance: "",
|
|
340
|
+
id: "1",
|
|
341
|
+
accessKey: accessKeySerialize(restartKey),
|
|
342
|
+
command: OpsCommandEnum.RESTARTPOD,
|
|
343
|
+
namespace: pod.namespace,
|
|
344
|
+
group: "",
|
|
345
|
+
pod: pod.name,
|
|
346
|
+
container: ""
|
|
347
|
+
};
|
|
348
|
+
let routeMessage = {
|
|
349
|
+
msgtype: "routemessage",
|
|
350
|
+
accessKey: accessKeySerialize(restartKey),
|
|
351
|
+
destChannel: InstanceMessageChannelEnum.OPS,
|
|
352
|
+
action: InstanceMessageActionEnum.ROUTE,
|
|
353
|
+
flow: InstanceMessageFlowEnum.IMMEDIATE,
|
|
354
|
+
type: InstanceMessageTypeEnum.SIGNAL,
|
|
355
|
+
channel: InstanceMessageChannelEnum.LOG,
|
|
356
|
+
instance,
|
|
357
|
+
data: opsMessage
|
|
358
|
+
};
|
|
359
|
+
websocket?.send(JSON.stringify(routeMessage));
|
|
360
|
+
}
|
|
361
|
+
};
|
|
254
362
|
const actionButtons = () => {
|
|
255
|
-
let hasViewKey = false;
|
|
363
|
+
let hasViewKey = false, hasRestartKey = false;
|
|
256
364
|
let cluster = resources.find((cluster2) => cluster2.name === selectedClusterName);
|
|
257
|
-
if (cluster)
|
|
258
|
-
|
|
365
|
+
if (cluster) {
|
|
366
|
+
hasViewKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW));
|
|
367
|
+
hasRestartKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART));
|
|
368
|
+
}
|
|
369
|
+
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, { title: "Download", onClick: onClickDownload, disabled: messages.length <= 1 }, /* @__PURE__ */ React.createElement(DownloadIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: () => clickStart(kwirthLogOptionsRef.current), title: "Play", disabled: started || !paused || selectedPodNames.length === 0 || !hasViewKey }, /* @__PURE__ */ React.createElement(PlayIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: onClickPause, 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)));
|
|
259
370
|
};
|
|
260
371
|
const statusButtons = (title) => {
|
|
261
372
|
const show = (level) => {
|
|
262
373
|
setShowStatusDialog(true);
|
|
263
374
|
setStatusLevel(level);
|
|
264
375
|
};
|
|
265
|
-
return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, 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) ? "
|
|
376
|
+
return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, 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) ? "orange" : "#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" } }))));
|
|
266
377
|
};
|
|
267
378
|
const statusClear = (level) => {
|
|
268
379
|
setStatusMessages(statusMessages.filter((m) => m.level !== level));
|
|
@@ -273,28 +384,28 @@ const EntityKwirthLogContent = () => {
|
|
|
273
384
|
setSelectedPodNames(podNames);
|
|
274
385
|
setSelectedContainerNames(containerNames);
|
|
275
386
|
};
|
|
276
|
-
const formatMessage = (
|
|
277
|
-
if (!
|
|
278
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null,
|
|
387
|
+
const formatMessage = (logLine) => {
|
|
388
|
+
if (!logLine.pod) {
|
|
389
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, logLine.text + "\n");
|
|
279
390
|
}
|
|
280
391
|
let podPrefix = /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
281
392
|
if (selectedPodNames.length !== 1) {
|
|
282
|
-
podPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "green" } },
|
|
393
|
+
podPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "green" } }, logLine.pod + " ");
|
|
283
394
|
}
|
|
284
395
|
let containerPrefix = /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
285
396
|
if (selectedContainerNames.length !== 1) {
|
|
286
|
-
containerPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "blue" } },
|
|
397
|
+
containerPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "blue" } }, logLine.container + " ");
|
|
287
398
|
}
|
|
288
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, podPrefix, containerPrefix,
|
|
399
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, podPrefix, containerPrefix, logLine.text + "\n");
|
|
289
400
|
};
|
|
290
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null,
|
|
401
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, 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/plugin-kwirth-log", annotation: ANNOTATION_KWIRTH_LOCATION }), isKwirthAvailable(entity) && !loading && resources && resources.length === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_CLUSTERS, entity }), isKwirthAvailable(entity) && !loading && resources && resources.length > 0 && resources.reduce((sum, cluster) => sum + cluster.data.length, 0) === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_PODS, entity }), isKwirthAvailable(entity) && !loading && resources && resources.length > 0 && resources.reduce((sum, cluster) => sum + cluster.data.length, 0) > 0 && /* @__PURE__ */ React.createElement(Box, { sx: { display: "flex", height: "70vh" } }, /* @__PURE__ */ React.createElement(Box, { sx: { width: "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, selectedClusterName, onSelect: onSelectCluster }))), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(Options, { options: kwirthLogOptionsRef.current, onChange: onChangeLogConfig, disabled: selectedContainerNames.length === 0 || started || paused.current }))))), /* @__PURE__ */ React.createElement(Box, { sx: { flexGrow: 1, flex: 1, overflow: "hidden", p: 1, maxWidth: "85%" } }, !selectedClusterName && /* @__PURE__ */ React.createElement("img", { src: KwirthLogLogo, 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, height: "100%", display: "flex", flexDirection: "column" } }, /* @__PURE__ */ React.createElement(
|
|
291
402
|
CardHeader,
|
|
292
403
|
{
|
|
293
404
|
title: statusButtons(selectedClusterName),
|
|
294
405
|
style: { marginTop: -4, marginBottom: 4, flexShrink: 0 },
|
|
295
406
|
action: actionButtons()
|
|
296
407
|
}
|
|
297
|
-
), /* @__PURE__ */ React.createElement(Typography, { style: { marginLeft: 16, marginBottom: 4 } }, /* @__PURE__ */ React.createElement(ObjectSelector, { cluster: resources.find((cluster) => cluster.name === selectedClusterName), onSelect: onSelectObject, disabled: selectedClusterName === "" || started || paused.current, selectedNamespaces, selectedPodNames, selectedContainerNames })), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(CardContent, { style: { overflow: "auto" } }, /* @__PURE__ */ React.createElement("pre", { ref: preRef }, messages.map((m) => formatMessage(m))), /* @__PURE__ */ React.createElement("span", { ref: lastRef })))))), showStatusDialog && /* @__PURE__ */ React.createElement(StatusLog, { level: statusLevel, onClose: () => setShowStatusDialog(false), statusMessages, onClear: statusClear }));
|
|
408
|
+
), /* @__PURE__ */ React.createElement(Typography, { style: { marginLeft: 16, marginBottom: 4 } }, /* @__PURE__ */ React.createElement(ObjectSelector, { cluster: resources.find((cluster) => cluster.name === selectedClusterName), onSelect: onSelectObject, disabled: selectedClusterName === "" || started || paused.current, selectedNamespaces, selectedPodNames, selectedContainerNames })), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(CardContent, { style: { flexGrow: 1, overflow: "hidden", display: "flex", flexDirection: "column" } }, /* @__PURE__ */ React.createElement(Box, { style: { overflowY: "auto", overflowX: "auto", width: "100%", flexGrow: 1 } }, /* @__PURE__ */ React.createElement("pre", { ref: preRef }, messages.map((m) => formatMessage(m))), /* @__PURE__ */ React.createElement("span", { ref: lastRef }))))))), showStatusDialog && /* @__PURE__ */ React.createElement(StatusLog, { level: statusLevel, onClose: () => setShowStatusDialog(false), statusMessages, onClear: statusClear }));
|
|
298
409
|
};
|
|
299
410
|
|
|
300
411
|
export { EntityKwirthLogContent };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityKwirthLogContent.esm.js","sources":["../../../src/components/EntityKwirthLogContent/EntityKwirthLogContent.tsx"],"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 React, { useRef, useState } from 'react'\r\nimport useAsync from 'react-use/esm/useAsync'\r\n\r\nimport { Progress, WarningPanel } from '@backstage/core-components'\r\nimport { useApi } from '@backstage/core-plugin-api'\r\nimport { ANNOTATION_KWIRTH_LOCATION, isKwirthAvailable, ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\nimport { MissingAnnotationEmptyState, useEntity } from '@backstage/plugin-catalog-react'\r\n\r\n// kwirthlog\r\nimport { kwirthLogApiRef } from '../../api'\r\nimport { accessKeySerialize, LogMessage, InstanceConfigActionEnum, InstanceConfigChannelEnum, InstanceConfigFlowEnum, InstanceConfigScopeEnum, InstanceConfigViewEnum, InstanceMessage, InstanceMessageTypeEnum, SignalMessage, SignalMessageLevelEnum, InstanceConfigObjectEnum, InstanceConfig } from '@jfvilas/kwirth-common'\r\n\r\n// kwirthlog components\r\nimport { ComponentNotFound, ErrorType } from '../ComponentNotFound'\r\nimport { Options } from '../Options'\r\nimport { ClusterList } from '../ClusterList'\r\nimport { ShowError } from '../ShowError'\r\nimport { StatusLog } from '../StatusLog'\r\n\r\n\r\n// Material-UI\r\nimport { Grid } from '@material-ui/core'\r\nimport { Card, CardHeader, CardContent } from '@material-ui/core'\r\nimport Divider from '@material-ui/core/Divider'\r\nimport IconButton from '@material-ui/core/IconButton'\r\nimport Typography from '@material-ui/core/Typography'\r\n\r\n// Icons\r\nimport PlayIcon from '@material-ui/icons/PlayArrow'\r\nimport PauseIcon from '@material-ui/icons/Pause'\r\nimport StopIcon from '@material-ui/icons/Stop'\r\nimport InfoIcon from '@material-ui/icons/Info'\r\nimport WarningIcon from '@material-ui/icons/Warning'\r\nimport ErrorIcon from '@material-ui/icons/Error'\r\nimport DownloadIcon from '@material-ui/icons/CloudDownload'\r\nimport KwirthLogLogo from '../../assets/kwirthlog-logo.svg'\r\nimport { ObjectSelector } from '../ObjectSelector'\r\n\r\nconst LOG_MAX_MESSAGES=1000;\r\n\r\nexport const EntityKwirthLogContent = () => { \r\n const { entity } = useEntity()\r\n const kwirthLogApi = useApi(kwirthLogApiRef)\r\n const [resources, setResources] = useState<ClusterValidPods[]>([])\r\n const [selectedClusterName, setSelectedClusterName] = useState('')\r\n const [_namespaceList, setNamespaceList] = useState<string[]>([]) //+++\r\n const [selectedNamespaces, setSelectedNamespaces] = useState<string[]>([])\r\n const [selectedPodNames, setSelectedPodNames] = useState<string[]>([])\r\n const [selectedContainerNames, setSelectedContainerNames] = useState<string[]>([])\r\n const [showError, setShowError] = useState('') //+++ review if this is needed once we have errorMessages\r\n const [started, setStarted] = useState(false)\r\n const [stopped, setStopped] = useState(true)\r\n const paused=useRef<boolean>(false)\r\n const [messages, setMessages] = useState<LogMessage[]>([])\r\n const [pendingMessages, setPendingMessages] = useState<LogMessage[]>([])\r\n const [statusMessages, setStatusMessages] = useState<SignalMessage[]>([])\r\n const [websocket, setWebsocket] = useState<WebSocket>()\r\n const kwirthLogOptionsRef = useRef<any>({timestamp:false, follow:true, fromStart:false})\r\n const [showStatusDialog, setShowStatusDialog] = useState(false)\r\n const [statusLevel, setStatusLevel] = useState<SignalMessageLevelEnum>(SignalMessageLevelEnum.INFO)\r\n const preRef = useRef<HTMLPreElement|null>(null)\r\n const lastRef = useRef<HTMLPreElement|null>(null)\r\n const [ backendVersion, setBackendVersion ] = useState<string>('')\r\n const { loading, error } = useAsync ( async () => {\r\n if (backendVersion==='') setBackendVersion(await kwirthLogApi.getVersion())\r\n var data = await kwirthLogApi.requestAccess(entity,'log', [InstanceConfigScopeEnum.VIEW,InstanceConfigScopeEnum.RESTART])\r\n setResources(data)\r\n })\r\n\r\n const clickStart = (options:any) => {\r\n if (!paused.current) {\r\n setStarted(true)\r\n paused.current=false\r\n setStopped(false)\r\n startLogViewer(options)\r\n }\r\n else {\r\n setMessages( (prev) => [ ...prev, ...pendingMessages])\r\n setPendingMessages([])\r\n paused.current=false\r\n setStarted(true)\r\n }\r\n }\r\n\r\n const clickPause = () => {\r\n setStarted(false)\r\n paused.current=true\r\n }\r\n\r\n const clickStop = () => {\r\n setStarted(false)\r\n setStopped(true)\r\n paused.current=false\r\n stopLogViewer()\r\n }\r\n\r\n const onSelectCluster = (name:string|undefined) => {\r\n if (name) {\r\n setSelectedClusterName(name)\r\n resources.filter(cluster => cluster.name===name).map ( x => {\r\n var namespaces=Array.from(new Set(x.data.map ( (p:any) => p.namespace))) as string[]\r\n setNamespaceList(namespaces)\r\n })\r\n setMessages([{\r\n channel: InstanceConfigChannelEnum.LOG,\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n text: 'Select namespace in order to decide which pod logs to view.',\r\n instance: ''\r\n }])\r\n setSelectedNamespaces([])\r\n setSelectedPodNames([])\r\n setSelectedContainerNames([])\r\n setStatusMessages([])\r\n clickStop()\r\n }\r\n }\r\n\r\n const processLogMessage = (wsEvent:any) => {\r\n let msg = JSON.parse(wsEvent.data) as InstanceMessage\r\n switch (msg.type) {\r\n case 'data':\r\n var lmsg = msg as LogMessage\r\n if (paused.current) {\r\n setPendingMessages((prev) => [ ...prev, lmsg ])\r\n }\r\n else {\r\n setMessages((prev) => {\r\n while (prev.length>LOG_MAX_MESSAGES-1) {\r\n prev.splice(0,1)\r\n }\r\n if (kwirthLogOptionsRef.current.follow && lastRef.current) lastRef.current.scrollIntoView({ behavior: 'instant', block: 'start' })\r\n return [ ...prev, lmsg ]\r\n })\r\n } \r\n break\r\n case 'signal':\r\n let smsg = msg as SignalMessage\r\n setStatusMessages ((prev) => [...prev, smsg])\r\n break\r\n default:\r\n console.log('Invalid message type:')\r\n console.log(msg)\r\n setStatusMessages ((prev) => [...prev, {\r\n channel: InstanceConfigChannelEnum.LOG,\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n level: SignalMessageLevelEnum.ERROR,\r\n text: 'Invalid message type received: '+msg.type,\r\n instance: ''\r\n }])\r\n break\r\n }\r\n }\r\n \r\n const websocketOnMessage = (wsEvent:any) => {\r\n let instanceMessage:InstanceMessage\r\n try {\r\n instanceMessage = JSON.parse(wsEvent.data) as InstanceMessage\r\n }\r\n catch (err) {\r\n console.log(err)\r\n console.log(wsEvent.data)\r\n return\r\n }\r\n\r\n switch(instanceMessage.channel) {\r\n case 'log':\r\n processLogMessage(wsEvent)\r\n break\r\n default:\r\n console.log('Invalid channel in message: ', instanceMessage)\r\n break\r\n }\r\n\r\n }\r\n\r\n const websocketOnOpen = (ws:WebSocket, options:any) => {\r\n let cluster=resources.find(cluster => cluster.name === selectedClusterName)\r\n if (!cluster) {\r\n //+++ setShowError(msg.text);\r\n return\r\n }\r\n let pods = cluster.data.filter(p => selectedNamespaces.includes(p.namespace))\r\n if (!pods) {\r\n //+++ setShowError(msg.text);\r\n return\r\n }\r\n console.log(`WS connected`)\r\n let accessKey = cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW)\r\n if (accessKey) {\r\n let containers:string[] = []\r\n if (selectedContainerNames.length>0) {\r\n for(var p of selectedPodNames) {\r\n for (var c of selectedContainerNames) {\r\n containers.push(p+'+'+c)\r\n }\r\n }\r\n }\r\n let iConfig:InstanceConfig = {\r\n channel: InstanceConfigChannelEnum.LOG,\r\n objects: InstanceConfigObjectEnum.PODS,\r\n action: InstanceConfigActionEnum.START,\r\n flow: InstanceConfigFlowEnum.REQUEST,\r\n instance: '',\r\n accessKey: accessKeySerialize(accessKey),\r\n scope: InstanceConfigScopeEnum.VIEW,\r\n view: (selectedContainerNames.length>0 ? InstanceConfigViewEnum.CONTAINER : InstanceConfigViewEnum.POD),\r\n namespace: selectedNamespaces.join(','),\r\n group: '',\r\n pod: selectedPodNames.map(p => p).join(','),\r\n container: containers.join(','),\r\n data: {\r\n timestamp: options.timestamp,\r\n previous: false,\r\n maxMessages: LOG_MAX_MESSAGES,\r\n fromStart: options.fromStart\r\n }\r\n }\r\n ws.send(JSON.stringify(iConfig))\r\n }\r\n else {\r\n // +++ error to user\r\n }\r\n }\r\n\r\n const startLogViewer = (options:any) => {\r\n let cluster=resources.find(cluster => cluster.name===selectedClusterName);\r\n if (!cluster) {\r\n //+++ show wargning\r\n return\r\n }\r\n\r\n setMessages([])\r\n try {\r\n let ws = new WebSocket(cluster.url)\r\n ws.onopen = () => websocketOnOpen(ws, options)\r\n ws.onmessage = (event) => websocketOnMessage(event)\r\n ws.onclose = (event) => websocketOnClose(event)\r\n setWebsocket(ws)\r\n }\r\n catch (err) {\r\n setMessages([ {\r\n channel: InstanceConfigChannelEnum.LOG,\r\n type: InstanceMessageTypeEnum.DATA,\r\n text: `Error opening log stream: ${err}`,\r\n instance: ''\r\n } ])\r\n }\r\n\r\n }\r\n\r\n const websocketOnClose = (_event:any) => {\r\n console.log(`WS disconnected`)\r\n setStarted(false)\r\n paused.current=false\r\n setStopped(true)\r\n }\r\n\r\n const stopLogViewer = () => {\r\n messages.push({\r\n channel: InstanceConfigChannelEnum.LOG,\r\n type: InstanceMessageTypeEnum.DATA,\r\n text: '============================================================================================================================',\r\n instance: ''\r\n })\r\n websocket?.close()\r\n }\r\n\r\n const onChangeLogConfig = (options:any) => {\r\n kwirthLogOptionsRef.current=options\r\n if (started) {\r\n clickStart(options)\r\n }\r\n }\r\n\r\n const handleDownload = () => {\r\n let content = preRef.current!.innerHTML.replaceAll('<pre>','').replaceAll('</pre>','\\n')\r\n content = content.replaceAll('<span style=\"color: green;\">','')\r\n content = content.replaceAll('<span style=\"color: blue;\">','')\r\n content = content.replaceAll('</span>','')\r\n let filename = selectedClusterName+'-'+selectedNamespaces+'-'+entity.metadata.name+'.txt'\r\n let mimeType:string = 'text/plain'\r\n \r\n const blob = new Blob([content], { type: mimeType })\r\n const url = URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = filename\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(url)\r\n }\r\n \r\n const actionButtons = () => {\r\n let hasViewKey=false\r\n let cluster=resources.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) hasViewKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW))\r\n\r\n return <>\r\n <IconButton title='Download' onClick={handleDownload} disabled={messages.length<=1}>\r\n <DownloadIcon />\r\n </IconButton>\r\n <IconButton onClick={() => clickStart(kwirthLogOptionsRef.current)} title=\"Play\" disabled={started || !paused || selectedPodNames.length === 0 || !hasViewKey}>\r\n <PlayIcon />\r\n </IconButton>\r\n <IconButton onClick={clickPause} title=\"Pause\" disabled={!((started && !paused.current) && selectedPodNames.length > 0)}>\r\n <PauseIcon />\r\n </IconButton>\r\n <IconButton onClick={clickStop} title=\"Stop\" disabled={stopped || selectedPodNames.length === 0}>\r\n <StopIcon />\r\n </IconButton>\r\n </>\r\n }\r\n\r\n const statusButtons = (title:string) => {\r\n const show = (level:SignalMessageLevelEnum) => {\r\n setShowStatusDialog(true)\r\n setStatusLevel(level)\r\n }\r\n\r\n return (\r\n <Grid container direction='row' >\r\n <Grid item>\r\n <Typography variant='h5'>{title}</Typography>\r\n </Grid>\r\n <Grid item style={{marginTop:'-8px'}}>\r\n <IconButton title=\"info\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.INFO)} onClick={() => show(SignalMessageLevelEnum.INFO)}>\r\n <InfoIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.INFO)?'blue':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"warning\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.WARNING)} onClick={() => show(SignalMessageLevelEnum.WARNING)} style={{marginLeft:'-16px'}}>\r\n <WarningIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.WARNING)?'gold':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"error\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.ERROR)} onClick={() => show(SignalMessageLevelEnum.ERROR)} style={{marginLeft:'-16px'}}>\r\n <ErrorIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.ERROR)?'red':'#BDBDBD'}}/>\r\n </IconButton>\r\n </Grid>\r\n </Grid>\r\n )\r\n }\r\n\r\n const statusClear = (level: SignalMessageLevelEnum) => {\r\n setStatusMessages(statusMessages.filter(m=> m.level!==level))\r\n setShowStatusDialog(false)\r\n }\r\n \r\n const onSelectObject = (namespaces:string[], podNames:string[], containerNames:string[]) => {\r\n setSelectedNamespaces(namespaces)\r\n setSelectedPodNames(podNames)\r\n setSelectedContainerNames(containerNames)\r\n }\r\n\r\n const formatMessage = (m:LogMessage) => {\r\n if (!m.pod) {\r\n return <>{m.text+'\\n'}</>\r\n }\r\n\r\n let podPrefix = <></>\r\n if (selectedPodNames.length !== 1) {\r\n podPrefix = <span style={{color:\"green\"}}>{m.pod+' '}</span>\r\n }\r\n\r\n let containerPrefix = <></>\r\n if (selectedContainerNames.length !== 1){\r\n containerPrefix = <span style={{color:\"blue\"}}>{m.container+' '}</span>\r\n }\r\n return <>{podPrefix}{containerPrefix}{m.text+'\\n'}</>\r\n }\r\n\r\n return (<>\r\n { showError!=='' && <ShowError message={showError} onClose={() => setShowError('')}/> }\r\n\r\n { loading && <Progress/> }\r\n\r\n {!isKwirthAvailable(entity) && !loading && error && (\r\n <WarningPanel title={'An error has ocurred while obtaining data from kuebernetes clusters.'} message={error?.message} />\r\n )}\r\n\r\n {!isKwirthAvailable(entity) && !loading && (\r\n <MissingAnnotationEmptyState readMoreUrl='https://github.com/jfvilas/plugin-kwirth-log' annotation={ANNOTATION_KWIRTH_LOCATION}/>\r\n )}\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length===0 &&\r\n <ComponentNotFound error={ErrorType.NO_CLUSTERS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length>0 && resources.reduce((sum,cluster) => sum+cluster.data.length, 0)===0 &&\r\n <ComponentNotFound error={ErrorType.NO_PODS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length>0 && resources.reduce((sum,cluster) => sum+cluster.data.length, 0)>0 &&\r\n <Grid container direction='row' spacing={3}>\r\n <Grid container item xs={2} direction='column' spacing={3}>\r\n <Grid item>\r\n <Card>\r\n <ClusterList resources={resources} selectedClusterName={selectedClusterName} onSelect={onSelectCluster}/>\r\n </Card>\r\n </Grid>\r\n <Grid item>\r\n <Card>\r\n <Options options={kwirthLogOptionsRef.current} onChange={onChangeLogConfig} disabled={selectedContainerNames.length === 0 || started || paused.current}/>\r\n </Card>\r\n </Grid>\r\n </Grid>\r\n\r\n <Grid item xs={10}>\r\n\r\n { !selectedClusterName && \r\n <img src={KwirthLogLogo} alt='No cluster selected' style={{ left:'40%', marginTop:'10%', width:'20%', position:'relative' }} />\r\n }\r\n\r\n { selectedClusterName && <>\r\n <Card style={{ maxHeight:'75vh'}}>\r\n <CardHeader\r\n title={statusButtons(selectedClusterName)}\r\n style={{marginTop:-4, marginBottom:4, flexShrink:0}}\r\n action={actionButtons()}\r\n />\r\n \r\n <Typography style={{marginLeft:16, marginBottom:4}}>\r\n <ObjectSelector cluster={resources.find(cluster => cluster.name === selectedClusterName)!} onSelect={onSelectObject} disabled={selectedClusterName === '' || started || paused.current} selectedNamespaces={selectedNamespaces} selectedPodNames={selectedPodNames} selectedContainerNames={selectedContainerNames}/>\r\n </Typography>\r\n <Divider/>\r\n <CardContent style={{ overflow: 'auto' }}>\r\n <pre ref={preRef}>\r\n { messages.map (m => formatMessage(m)) }\r\n </pre>\r\n <span ref={lastRef}></span>\r\n </CardContent>\r\n </Card>\r\n </>}\r\n\r\n </Grid>\r\n </Grid>\r\n }\r\n\r\n { showStatusDialog && <StatusLog level={statusLevel} onClose={() => setShowStatusDialog(false)} statusMessages={statusMessages} onClear={statusClear}/>}\r\n </>)\r\n}\r\n"],"names":["cluster","p"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityKwirthLogContent.esm.js","sources":["../../../src/components/EntityKwirthLogContent/EntityKwirthLogContent.tsx"],"sourcesContent":["/*\r\nCopyright 2025 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 React, { useRef, useState } from 'react'\r\nimport useAsync from 'react-use/esm/useAsync'\r\n\r\nimport { Progress, WarningPanel } from '@backstage/core-components'\r\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api'\r\nimport { ANNOTATION_KWIRTH_LOCATION, isKwirthAvailable, ClusterValidPods, PodData, ILogLine, IStatusLine } from '@jfvilas/plugin-kwirth-common'\r\nimport { MissingAnnotationEmptyState, useEntity } from '@backstage/plugin-catalog-react'\r\n\r\n// kwirthlog\r\nimport { kwirthLogApiRef } from '../../api'\r\nimport { accessKeySerialize, ILogMessage, InstanceMessageActionEnum, InstanceConfigScopeEnum, InstanceConfigViewEnum, InstanceMessage, InstanceMessageTypeEnum, SignalMessage, SignalMessageLevelEnum, InstanceConfigObjectEnum, InstanceConfig, InstanceMessageFlowEnum, InstanceMessageChannelEnum, IOpsMessage, OpsCommandEnum, IRouteMessage, IOpsMessageResponse } from '@jfvilas/kwirth-common'\r\n\r\n// kwirthlog components\r\nimport { ComponentNotFound, ErrorType } from '../ComponentNotFound'\r\nimport { ObjectSelector } from '../ObjectSelector'\r\nimport { Options } from '../Options'\r\nimport { ClusterList } from '../ClusterList'\r\nimport { StatusLog } from '../StatusLog'\r\n\r\n\r\n// Material-UI\r\nimport { Grid, Card, CardHeader, CardContent, Box, Button } from '@material-ui/core'\r\nimport Divider from '@material-ui/core/Divider'\r\nimport IconButton from '@material-ui/core/IconButton'\r\nimport Typography from '@material-ui/core/Typography'\r\n\r\n// Icons\r\nimport PlayIcon from '@material-ui/icons/PlayArrow'\r\nimport PauseIcon from '@material-ui/icons/Pause'\r\nimport StopIcon from '@material-ui/icons/Stop'\r\nimport InfoIcon from '@material-ui/icons/Info'\r\nimport WarningIcon from '@material-ui/icons/Warning'\r\nimport ErrorIcon from '@material-ui/icons/Error'\r\nimport DownloadIcon from '@material-ui/icons/CloudDownload'\r\nimport KwirthLogLogo from '../../assets/kwirthlog-logo.svg'\r\nimport RefreshIcon from '@material-ui/icons/Refresh'\r\n\r\nconst LOG_MAX_MESSAGES=1000\r\n\r\nexport const EntityKwirthLogContent = (props:{ enableRestart: boolean }) => { \r\n const { entity } = useEntity()\r\n const kwirthLogApi = useApi(kwirthLogApiRef)\r\n const alertApi = useApi(alertApiRef)\r\n const [resources, setResources] = useState<ClusterValidPods[]>([])\r\n const [selectedClusterName, setSelectedClusterName] = useState('')\r\n const [selectedNamespaces, setSelectedNamespaces] = useState<string[]>([])\r\n const [selectedPodNames, setSelectedPodNames] = useState<string[]>([])\r\n const [selectedContainerNames, setSelectedContainerNames] = useState<string[]>([])\r\n const [started, setStarted] = useState(false)\r\n const [stopped, setStopped] = useState(true)\r\n const paused=useRef<boolean>(false)\r\n const [messages, setMessages] = useState<ILogLine[]>([])\r\n const [pendingMessages, setPendingMessages] = useState<ILogLine[]>([])\r\n const [statusMessages, setStatusMessages] = useState<IStatusLine[]>([])\r\n const [websocket, setWebsocket] = useState<WebSocket>()\r\n const [instance, setInstance] = useState<string>()\r\n const kwirthLogOptionsRef = useRef<any>({timestamp:false, follow:true, fromStart:false})\r\n const [showStatusDialog, setShowStatusDialog] = useState(false)\r\n const [statusLevel, setStatusLevel] = useState<SignalMessageLevelEnum>(SignalMessageLevelEnum.INFO)\r\n const preRef = useRef<HTMLPreElement|null>(null)\r\n const lastRef = useRef<HTMLPreElement|null>(null)\r\n const [ backendVersion, setBackendVersion ] = useState<string>('')\r\n const { loading, error } = useAsync ( async () => {\r\n if (backendVersion==='') setBackendVersion(await kwirthLogApi.getVersion())\r\n let reqScopes = [InstanceConfigScopeEnum.VIEW]\r\n if (props.enableRestart) reqScopes.push(InstanceConfigScopeEnum.RESTART)\r\n let data:ClusterValidPods[] = await kwirthLogApi.requestAccess(entity, InstanceMessageChannelEnum.LOG, reqScopes)\r\n setResources(data)\r\n })\r\n const buffer = useRef<Map<string,string>>(new Map())\r\n\r\n\r\n const clickStart = (options:any) => {\r\n if (!paused.current) {\r\n setStarted(true)\r\n paused.current=false\r\n setStopped(false)\r\n startLogViewer(options)\r\n }\r\n else {\r\n setMessages( (prev) => [ ...prev, ...pendingMessages])\r\n setPendingMessages([])\r\n paused.current=false\r\n setStarted(true)\r\n }\r\n }\r\n\r\n const onClickPause = () => {\r\n setStarted(false)\r\n paused.current=true\r\n }\r\n\r\n const onClickStop = () => {\r\n setStarted(false)\r\n setStopped(true)\r\n paused.current=false\r\n stopLogViewer()\r\n }\r\n\r\n const onSelectCluster = (name:string|undefined) => {\r\n if (name) {\r\n setSelectedClusterName(name)\r\n setMessages([{\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n text: 'Select namespace in order to decide which pod logs to view.',\r\n namespace: '',\r\n pod: '',\r\n container: ''\r\n }])\r\n setSelectedNamespaces([])\r\n setSelectedPodNames([])\r\n setSelectedContainerNames([])\r\n setStatusMessages([])\r\n onClickStop()\r\n }\r\n }\r\n\r\n const processLogMessage = (wsEvent:any) => {\r\n let instanceMessage = JSON.parse(wsEvent.data) as InstanceMessage\r\n switch (instanceMessage.type) {\r\n case InstanceMessageTypeEnum.DATA:\r\n let logMessage = instanceMessage as ILogMessage\r\n let bname = logMessage.namespace+'/'+logMessage.pod+'/'+logMessage.container\r\n let text = logMessage.text\r\n if (!buffer.current.has(bname)) buffer.current.set(bname,'')\r\n if (buffer.current.get(bname)) {\r\n text = buffer.current.get(bname) + text\r\n buffer.current.set(bname,'')\r\n }\r\n if (!text.endsWith('\\n')) {\r\n let i = text.lastIndexOf('\\n')\r\n buffer.current.set(bname,text.substring(i))\r\n text = text.substring(0,i)\r\n }\r\n\r\n for (let line of text.split('\\n')) {\r\n if (line.trim() === '') continue\r\n\r\n let logLine:ILogLine = {\r\n text: line,\r\n namespace: logMessage.namespace,\r\n pod: logMessage.pod,\r\n container: logMessage.container,\r\n type: logMessage.type\r\n }\r\n\r\n if (paused.current) {\r\n setPendingMessages((prev) => [ ...prev, logLine ])\r\n }\r\n else {\r\n setMessages((prev) => {\r\n while (prev.length>LOG_MAX_MESSAGES-1) {\r\n prev.splice(0,1)\r\n }\r\n if (kwirthLogOptionsRef.current.follow && lastRef.current) lastRef.current.scrollIntoView({ behavior: 'instant', block: 'start' })\r\n return [ ...prev, logLine ]\r\n })\r\n }\r\n }\r\n break\r\n case InstanceMessageTypeEnum.SIGNAL:\r\n if (instanceMessage.flow === InstanceMessageFlowEnum.RESPONSE && instanceMessage.action === InstanceMessageActionEnum.START) {\r\n if (instanceMessage.instance!=='')\r\n setInstance(instanceMessage.instance)\r\n else {\r\n let signalMessage = instanceMessage as SignalMessage\r\n alertApi.post({ message: signalMessage.text, severity:'error', display:'transient' })\r\n }\r\n }\r\n else {\r\n let signalMessage = instanceMessage as SignalMessage\r\n addMessage(signalMessage.level, signalMessage.text)\r\n switch(signalMessage.level) {\r\n case SignalMessageLevelEnum.INFO:\r\n alertApi.post({ message: signalMessage.text, severity:'info', display:'transient' })\r\n break\r\n case SignalMessageLevelEnum.WARNING:\r\n alertApi.post({ message: signalMessage.text, severity:'warning', display:'transient' })\r\n break\r\n case SignalMessageLevelEnum.ERROR:\r\n alertApi.post({ message: signalMessage.text, severity:'error', display:'transient' })\r\n break\r\n default:\r\n alertApi.post({ message: signalMessage.text, severity:'success', display:'transient' })\r\n break\r\n }\r\n }\r\n break\r\n default:\r\n addMessage(SignalMessageLevelEnum.ERROR, 'Invalid message type received: ' + instanceMessage.type)\r\n alertApi.post({ message: 'Invalid message type received: ' + instanceMessage.type, severity:'error', display:'transient' })\r\n break\r\n }\r\n }\r\n\r\n const addMessage = (level:SignalMessageLevelEnum, text:string) => {\r\n setStatusMessages ((prev) => [...prev, {\r\n level,\r\n text,\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n }])\r\n }\r\n\r\n const websocketOnMessage = (wsEvent:any) => {\r\n let instanceMessage:InstanceMessage\r\n try {\r\n instanceMessage = JSON.parse(wsEvent.data) as InstanceMessage\r\n }\r\n catch (err) {\r\n console.log(err)\r\n console.log(wsEvent.data)\r\n return\r\n }\r\n\r\n switch(instanceMessage.channel) {\r\n case InstanceMessageChannelEnum.LOG:\r\n processLogMessage(wsEvent)\r\n break\r\n case InstanceMessageChannelEnum.OPS:\r\n let opsMessage = instanceMessage as IOpsMessageResponse\r\n if (opsMessage.data?.data) \r\n addMessage (SignalMessageLevelEnum.WARNING, 'Operations message: '+opsMessage.data.data)\r\n else\r\n addMessage (SignalMessageLevelEnum.WARNING, 'Operations message: '+JSON.stringify(opsMessage))\r\n break\r\n default:\r\n addMessage (SignalMessageLevelEnum.ERROR, 'Invalid channel in message: '+instanceMessage.channel)\r\n addMessage (SignalMessageLevelEnum.ERROR, 'Invalid message: '+JSON.stringify(instanceMessage))\r\n break\r\n }\r\n }\r\n\r\n const websocketOnOpen = (ws:WebSocket, options:any) => {\r\n let cluster=resources.find(cluster => cluster.name === selectedClusterName)\r\n if (!cluster) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No cluster selected')\r\n return\r\n }\r\n let pods = cluster.data.filter(p => selectedNamespaces.includes(p.namespace))\r\n if (!pods) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No pods found')\r\n return\r\n }\r\n console.log(`WS connected`)\r\n let accessKey = cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW)\r\n if (accessKey) {\r\n let containers:string[] = []\r\n if (selectedContainerNames.length>0) {\r\n for(var p of selectedPodNames) {\r\n for (var c of selectedContainerNames) {\r\n containers.push(p+'+'+c)\r\n }\r\n }\r\n }\r\n let iConfig:InstanceConfig = {\r\n channel: InstanceMessageChannelEnum.LOG,\r\n objects: InstanceConfigObjectEnum.PODS,\r\n action: InstanceMessageActionEnum.START,\r\n flow: InstanceMessageFlowEnum.REQUEST,\r\n instance: '',\r\n accessKey: accessKeySerialize(accessKey),\r\n scope: InstanceConfigScopeEnum.VIEW,\r\n view: (selectedContainerNames.length > 0 ? InstanceConfigViewEnum.CONTAINER : InstanceConfigViewEnum.POD),\r\n namespace: selectedNamespaces.join(','),\r\n group: '',\r\n pod: selectedPodNames.map(p => p).join(','),\r\n container: containers.join(','),\r\n data: {\r\n timestamp: options.timestamp,\r\n previous: false,\r\n maxMessages: LOG_MAX_MESSAGES,\r\n fromStart: options.fromStart\r\n },\r\n type: InstanceMessageTypeEnum.SIGNAL\r\n }\r\n ws.send(JSON.stringify(iConfig))\r\n }\r\n else {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No accessKey for starting log streaming')\r\n return\r\n }\r\n }\r\n\r\n const startLogViewer = (options:any) => {\r\n let cluster=resources.find(cluster => cluster.name===selectedClusterName);\r\n if (!cluster) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No cluster selected')\r\n return\r\n }\r\n\r\n setMessages([])\r\n try {\r\n let ws = new WebSocket(cluster.url)\r\n ws.onopen = () => websocketOnOpen(ws, options)\r\n ws.onmessage = (event) => websocketOnMessage(event)\r\n ws.onclose = (event) => websocketOnClose(event)\r\n setWebsocket(ws)\r\n }\r\n catch (err) {\r\n setMessages([ {\r\n type: InstanceMessageTypeEnum.DATA,\r\n text: `Error opening log stream: ${err}`,\r\n namespace: '',\r\n pod: '',\r\n container: ''\r\n } ])\r\n }\r\n\r\n }\r\n\r\n const websocketOnClose = (_event:any) => {\r\n console.log(`WS disconnected`)\r\n setStarted(false)\r\n paused.current=false\r\n setStopped(true)\r\n }\r\n\r\n const stopLogViewer = () => {\r\n messages.push({\r\n type: InstanceMessageTypeEnum.DATA,\r\n text: '============================================================================================================================',\r\n namespace: '',\r\n pod: '',\r\n container: ''\r\n })\r\n websocket?.close()\r\n }\r\n\r\n const onChangeLogConfig = (options:any) => {\r\n kwirthLogOptionsRef.current=options\r\n if (started) {\r\n clickStart(options)\r\n }\r\n }\r\n\r\n const onClickDownload = () => {\r\n let content = preRef.current!.innerHTML.replaceAll('<pre>','').replaceAll('</pre>','\\n')\r\n content = content.replaceAll('<span style=\"color: green;\">','')\r\n content = content.replaceAll('<span style=\"color: blue;\">','')\r\n content = content.replaceAll('</span>','')\r\n let filename = selectedClusterName+'-'+selectedNamespaces+'-'+entity.metadata.name+'.txt'\r\n let mimeType:string = 'text/plain'\r\n \r\n const blob = new Blob([content], { type: mimeType })\r\n const url = URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = filename\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(url)\r\n }\r\n\r\n const onClickRestart = () => {\r\n // we perform a route command from channel 'log' to channel 'ops'\r\n var cluster=resources.find(cluster => cluster.name===selectedClusterName);\r\n if (!cluster) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No cluster selected')\r\n return\r\n }\r\n let restartKey = cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART)\r\n if (!restartKey) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No access key present')\r\n return\r\n }\r\n if (!instance) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No instance has been established')\r\n return\r\n }\r\n\r\n let pods:PodData[] = (cluster.data as PodData[]).filter(pod => selectedNamespaces.includes(pod.namespace))\r\n for (let pod of pods) {\r\n let opsMessage:IOpsMessage = {\r\n msgtype: 'opsmessage',\r\n action: InstanceMessageActionEnum.COMMAND,\r\n flow: InstanceMessageFlowEnum.IMMEDIATE,\r\n type: InstanceMessageTypeEnum.DATA,\r\n channel: InstanceMessageChannelEnum.OPS,\r\n instance: '',\r\n id: '1',\r\n accessKey: accessKeySerialize(restartKey),\r\n command: OpsCommandEnum.RESTARTPOD,\r\n namespace: pod.namespace,\r\n group: '',\r\n pod: pod.name,\r\n container: ''\r\n }\r\n let routeMessage: IRouteMessage = {\r\n msgtype: 'routemessage',\r\n accessKey: accessKeySerialize(restartKey),\r\n destChannel: InstanceMessageChannelEnum.OPS,\r\n action: InstanceMessageActionEnum.ROUTE,\r\n flow: InstanceMessageFlowEnum.IMMEDIATE,\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n channel: InstanceMessageChannelEnum.LOG,\r\n instance: instance,\r\n data: opsMessage\r\n }\r\n websocket?.send(JSON.stringify(routeMessage))\r\n }\r\n }\r\n\r\n const actionButtons = () => {\r\n let hasViewKey=false, hasRestartKey = false\r\n let cluster=resources.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n hasViewKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW))\r\n hasRestartKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART))\r\n }\r\n\r\n return <>\r\n { props.enableRestart &&\r\n <IconButton title='Restart' onClick={onClickRestart} disabled={selectedPodNames.length === 0 || !hasRestartKey || !websocket || !started}>\r\n <RefreshIcon />\r\n </IconButton>\r\n }\r\n <IconButton title='Download' onClick={onClickDownload} disabled={messages.length<=1}>\r\n <DownloadIcon />\r\n </IconButton>\r\n <IconButton onClick={() => clickStart(kwirthLogOptionsRef.current)} title=\"Play\" disabled={started || !paused || selectedPodNames.length === 0 || !hasViewKey}>\r\n <PlayIcon />\r\n </IconButton>\r\n <IconButton onClick={onClickPause} title=\"Pause\" disabled={!((started && !paused.current) && selectedPodNames.length > 0)}>\r\n <PauseIcon />\r\n </IconButton>\r\n <IconButton onClick={onClickStop} title=\"Stop\" disabled={stopped || selectedPodNames.length === 0}>\r\n <StopIcon />\r\n </IconButton>\r\n </>\r\n }\r\n\r\n const statusButtons = (title:string) => {\r\n const show = (level:SignalMessageLevelEnum) => {\r\n setShowStatusDialog(true)\r\n setStatusLevel(level)\r\n }\r\n\r\n return (\r\n <Grid container direction='row' >\r\n <Grid item>\r\n <Typography variant='h5'>{title}</Typography>\r\n </Grid>\r\n <Grid item style={{marginTop:'-8px'}}>\r\n <IconButton title=\"info\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.INFO)} onClick={() => show(SignalMessageLevelEnum.INFO)}>\r\n <InfoIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.INFO)?'blue':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"warning\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.WARNING)} onClick={() => show(SignalMessageLevelEnum.WARNING)} style={{marginLeft:'-16px'}}>\r\n <WarningIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.WARNING)?'orange':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"error\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.ERROR)} onClick={() => show(SignalMessageLevelEnum.ERROR)} style={{marginLeft:'-16px'}}>\r\n <ErrorIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.ERROR)?'red':'#BDBDBD'}}/>\r\n </IconButton>\r\n </Grid>\r\n </Grid>\r\n )\r\n }\r\n\r\n const statusClear = (level: SignalMessageLevelEnum) => {\r\n setStatusMessages(statusMessages.filter(m=> m.level!==level))\r\n setShowStatusDialog(false)\r\n }\r\n \r\n const onSelectObject = (namespaces:string[], podNames:string[], containerNames:string[]) => {\r\n setSelectedNamespaces(namespaces)\r\n setSelectedPodNames(podNames)\r\n setSelectedContainerNames(containerNames)\r\n }\r\n\r\n const formatMessage = (logLine:ILogLine) => {\r\n if (!logLine.pod) {\r\n return <>{logLine.text+'\\n'}</>\r\n }\r\n\r\n let podPrefix = <></>\r\n if (selectedPodNames.length !== 1) {\r\n podPrefix = <span style={{color:\"green\"}}>{logLine.pod+' '}</span>\r\n }\r\n\r\n let containerPrefix = <></>\r\n if (selectedContainerNames.length !== 1){\r\n containerPrefix = <span style={{color:\"blue\"}}>{logLine.container+' '}</span>\r\n }\r\n return <>{podPrefix}{containerPrefix}{logLine.text+'\\n'}</>\r\n }\r\n\r\n return (<>\r\n\r\n { loading && <Progress/> }\r\n\r\n {!isKwirthAvailable(entity) && !loading && error && (\r\n <WarningPanel title={'An error has ocurred while obtaining data from kuebernetes clusters.'} message={error?.message} />\r\n )}\r\n\r\n {!isKwirthAvailable(entity) && !loading && (\r\n <MissingAnnotationEmptyState readMoreUrl='https://github.com/jfvilas/plugin-kwirth-log' annotation={ANNOTATION_KWIRTH_LOCATION}/>\r\n )}\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length===0 &&\r\n <ComponentNotFound error={ErrorType.NO_CLUSTERS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length>0 && resources.reduce((sum,cluster) => sum+cluster.data.length, 0)===0 &&\r\n <ComponentNotFound error={ErrorType.NO_PODS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length>0 && resources.reduce((sum,cluster) => sum+cluster.data.length, 0)>0 &&\r\n <Box sx={{ display: 'flex', height:'70vh'}}>\r\n <Box sx={{ width: '200px'}}>\r\n <Grid container direction='column'>\r\n <Grid item> \r\n <Card>\r\n <ClusterList resources={resources} selectedClusterName={selectedClusterName} onSelect={onSelectCluster}/>\r\n </Card>\r\n </Grid>\r\n <Grid item>\r\n <Card>\r\n <Options options={kwirthLogOptionsRef.current} onChange={onChangeLogConfig} disabled={selectedContainerNames.length === 0 || started || paused.current}/>\r\n </Card>\r\n </Grid>\r\n </Grid>\r\n </Box>\r\n\r\n <Box sx={{ flexGrow: 1, flex:1, overflow:'hidden', p:1, maxWidth:'85%' }}>\r\n\r\n { !selectedClusterName && \r\n <img src={KwirthLogLogo} alt='No cluster selected' style={{ left:'40%', marginTop:'10%', width:'20%', position:'relative' }} />\r\n }\r\n\r\n { selectedClusterName && <>\r\n <Card style={{ marginTop:-8, height:'100%', display:'flex', flexDirection:'column' }}>\r\n <CardHeader\r\n title={statusButtons(selectedClusterName)}\r\n style={{marginTop:-4, marginBottom:4, flexShrink:0}}\r\n action={actionButtons()}\r\n />\r\n \r\n <Typography style={{marginLeft:16, marginBottom:4}}>\r\n <ObjectSelector cluster={resources.find(cluster => cluster.name === selectedClusterName)!} onSelect={onSelectObject} disabled={selectedClusterName === '' || started || paused.current} selectedNamespaces={selectedNamespaces} selectedPodNames={selectedPodNames} selectedContainerNames={selectedContainerNames}/>\r\n </Typography>\r\n <Divider/>\r\n {/* <CardContent>\r\n <Box style={{ display:'flex', flexDirection:'column', overflowY:'auto', overflowX:'auto', width:'100%', flexGrow:1, height:'55vh'}}> */}\r\n <CardContent style={{ flexGrow: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>\r\n <Box style={{ overflowY: 'auto', overflowX: 'auto', width: '100%', flexGrow: 1 }}>\r\n\r\n <pre ref={preRef}>\r\n { messages.map (m => formatMessage(m)) }\r\n </pre>\r\n <span ref={lastRef}/>\r\n </Box> \r\n {/* <Box style={{ overflowY: 'auto', overflowX:'auto', whiteSpace: 'nowrap', maxHeight:'60vh' }}>\r\n <pre ref={preRef}>\r\n { messages.map (m => formatMessage(m)) }\r\n </pre>\r\n <span ref={lastRef}></span>\r\n </Box> */}\r\n </CardContent>\r\n </Card>\r\n </>}\r\n </Box>\r\n </Box>\r\n }\r\n { showStatusDialog && <StatusLog level={statusLevel} onClose={() => setShowStatusDialog(false)} statusMessages={statusMessages} onClear={statusClear}/>}\r\n </>)\r\n}\r\n"],"names":["cluster","p"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import FormControl from '@material-ui/core/FormControl';
|
|
3
3
|
import Select from '@material-ui/core/Select';
|
|
4
4
|
import MenuItem from '@material-ui/core/MenuItem';
|
|
5
|
-
import { Grid, Chip,
|
|
5
|
+
import { Grid, Chip, Checkbox, ListItemText } from '@material-ui/core';
|
|
6
6
|
import { InstanceConfigScopeEnum, parseResources } from '@jfvilas/kwirth-common';
|
|
7
7
|
|
|
8
8
|
const ObjectSelector = (props) => {
|
|
@@ -44,8 +44,8 @@ const ObjectSelector = (props) => {
|
|
|
44
44
|
if (!props.cluster.accessKeys.has(InstanceConfigScopeEnum.VIEW)) return false;
|
|
45
45
|
let accessKey = props.cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW);
|
|
46
46
|
if (accessKey) {
|
|
47
|
-
let resources = parseResources(accessKey
|
|
48
|
-
return resources.find((
|
|
47
|
+
let resources = parseResources(accessKey.resources);
|
|
48
|
+
return resources.find((resource) => resource.namespaces === namespace);
|
|
49
49
|
} else return false;
|
|
50
50
|
};
|
|
51
51
|
const getPodList = () => {
|
|
@@ -73,9 +73,9 @@ const ObjectSelector = (props) => {
|
|
|
73
73
|
else
|
|
74
74
|
return /* @__PURE__ */ React.createElement(Chip, { component: "span", key: index, label: ns, size: "small", color: "secondary", variant: "outlined" });
|
|
75
75
|
}
|
|
76
|
-
})), /* @__PURE__ */ React.createElement(Grid, { container: true, item: true, xs: 12, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(FormControl, { size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(Select, { value: props.selectedPodNames,
|
|
76
|
+
})), /* @__PURE__ */ React.createElement(Grid, { container: true, item: true, xs: 12, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(FormControl, { size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(Select, { value: props.selectedPodNames, MenuProps: { variant: "menu" }, multiple: true, onChange: onPodNameChange, renderValue: (selected) => selected.join(", "), disabled: props.disabled || props.selectedNamespaces.length === 0 || getPodList().length === 1 }, getPodList().map((pod) => {
|
|
77
77
|
return /* @__PURE__ */ React.createElement(MenuItem, { key: pod.name, value: pod.name }, /* @__PURE__ */ React.createElement(Checkbox, { checked: props.selectedPodNames.includes(pod.name) }), /* @__PURE__ */ React.createElement(ListItemText, { primary: pod.name }));
|
|
78
|
-
})))), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(FormControl, { size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(Select, { value: props.selectedContainerNames, multiple: true, onChange: onContainerNameChange, renderValue: (selected) => selected.join(", "), disabled: props.disabled || props.selectedPodNames.length === 0 || getContainerList().length === 1 }, getContainerList().map((container) => {
|
|
78
|
+
})))), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(FormControl, { size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(Select, { value: props.selectedContainerNames, MenuProps: { variant: "menu" }, multiple: true, onChange: onContainerNameChange, renderValue: (selected) => selected.join(", "), disabled: props.disabled || props.selectedPodNames.length === 0 || getContainerList().length === 1 }, getContainerList().map((container) => {
|
|
79
79
|
return /* @__PURE__ */ React.createElement(MenuItem, { key: container, value: container }, /* @__PURE__ */ React.createElement(Checkbox, { checked: props.selectedContainerNames.includes(container) }), /* @__PURE__ */ React.createElement(ListItemText, { primary: container }));
|
|
80
80
|
}))))));
|
|
81
81
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectSelector.esm.js","sources":["../../../src/components/ObjectSelector/ObjectSelector.tsx"],"sourcesContent":["import React, { useState } from 'react'\r\nimport { ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\nimport FormControl from '@material-ui/core/FormControl'\r\nimport Select from '@material-ui/core/Select'\r\nimport MenuItem from '@material-ui/core/MenuItem'\r\nimport { Checkbox, Chip, Grid, Input, ListItemText } from '@material-ui/core'\r\nimport { InstanceConfigScopeEnum, parseResources } from '@jfvilas/kwirth-common'\r\n\r\ninterface IProps {\r\n onSelect: (namespaces:string[], podNames:string[], containerNames:string[]) => void,\r\n cluster: ClusterValidPods,\r\n selectedNamespaces: string[],\r\n selectedPodNames: string[],\r\n selectedContainerNames: string[],\r\n disabled: boolean\r\n}\r\n\r\nconst ObjectSelector = (props: IProps) => {\r\n const [render, setRender] = useState(false)\r\n let pods = props.cluster.data\r\n let namespaceList = Array.from(new Set(pods.map(p => p.namespace)))\r\n\r\n const onNamespaceChange = (namespace:string) => {\r\n let i = props.selectedNamespaces.indexOf(namespace)\r\n if (i>=0)\r\n props.selectedNamespaces.splice(i,1)\r\n else\r\n props.selectedNamespaces.push(namespace)\r\n\r\n props.selectedPodNames.splice(0,props.selectedPodNames.length)\r\n let pods = getPodList()\r\n if (pods.length===1) props.selectedPodNames.push( ...pods.map(p => p.name) )\r\n\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n let containers = getContainerList()\r\n if (containers.length===1) {\r\n props.selectedContainerNames.push(...containers)\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n }\r\n\r\n setRender(!render)\r\n };\r\n\r\n const onPodNameChange = (event : any) => {\r\n props.selectedPodNames.splice(0,props.selectedPodNames.length)\r\n props.selectedPodNames.push( ...event.target.value )\r\n\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n let containers = getContainerList()\r\n if (containers.length===1) props.selectedContainerNames.push(...containers)\r\n\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n\r\n setRender(!render)\r\n };\r\n\r\n const onContainerNameChange = (event : any) => {\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n props.selectedContainerNames.push( ...event.target.value )\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n };\r\n\r\n const existAccessKey = (namespace:string) => {\r\n if (!props.cluster.accessKeys.has(InstanceConfigScopeEnum.VIEW)) return false\r\n let accessKey = props.cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW)\r\n if (accessKey) {\r\n let resources = parseResources(accessKey?.resource)\r\n return (resources.find(r => r.namespace === namespace))\r\n }\r\n else return false\r\n\r\n }\r\n\r\n const getPodList = () => {\r\n return Array.from(pods.filter(m => props.selectedNamespaces.includes(m.namespace)))\r\n }\r\n\r\n const getContainerList = () => {\r\n if (props.selectedNamespaces.length===0 || props.selectedPodNames.length===0) return []\r\n let validpods = pods.filter(pod => props.selectedNamespaces.includes(pod.namespace))\r\n validpods = validpods.filter(p => props.selectedPodNames.includes(p.name))\r\n let validcontainers:string[] = []\r\n for (var p of validpods) {\r\n validcontainers.push ( ...p.containers )\r\n }\r\n return Array.from(new Set(validcontainers))\r\n }\r\n\r\n return (\r\n <Grid container direction='column' spacing={0} style={{marginBottom:6, width:'100%'}}>\r\n <Grid item>\r\n {\r\n namespaceList.map ((ns,index) => {\r\n if (props.disabled) {\r\n if (existAccessKey(ns))\r\n return <Chip component={'span'} key={index} label={ns as string} variant={props.selectedNamespaces.includes(ns)?'default':'outlined'} size='small' color='default' />\r\n else\r\n return <Chip component={'span'} key={index} label={ns as string} size='small' color='default' variant={'outlined'}/>\r\n }\r\n else {\r\n if (existAccessKey(ns))\r\n return <Chip component={'span'} key={index} label={ns as string} onClick={() => onNamespaceChange(ns)} variant={props.selectedNamespaces.includes(ns)?'default':'outlined'} size='small' color='primary' />\r\n else\r\n return <Chip component={'span'} key={index} label={ns as string} size='small' color='secondary' variant={'outlined'}/>\r\n }\r\n })\r\n }\r\n </Grid>\r\n <Grid container item xs={12} spacing={2}>\r\n <Grid item xs={6}>\r\n <FormControl size='small' fullWidth>\r\n <Select value={props.selectedPodNames} input={<Input />} multiple onChange={onPodNameChange} renderValue={(selected) => (selected as string[]).join(', ')} disabled={props.disabled || props.selectedNamespaces.length===0 || getPodList().length===1}>\r\n {\r\n getPodList().map(pod => {\r\n return (\r\n <MenuItem key={pod.name} value={pod.name}>\r\n <Checkbox checked={props.selectedPodNames.includes(pod.name)} />\r\n <ListItemText primary={pod.name} />\r\n </MenuItem>\r\n )\r\n })\r\n }\r\n </Select>\r\n </FormControl>\r\n </Grid>\r\n <Grid item xs={6}>\r\n <FormControl size='small' fullWidth>\r\n <Select value={props.selectedContainerNames} multiple onChange={onContainerNameChange} renderValue={(selected) => (selected as string[]).join(', ')} disabled={props.disabled || props.selectedPodNames.length===0 || getContainerList().length===1}>\r\n {\r\n getContainerList().map(container => {\r\n return (\r\n <MenuItem key={container} value={container}>\r\n <Checkbox checked={props.selectedContainerNames.includes(container)} />\r\n <ListItemText primary={container} />\r\n </MenuItem>\r\n )\r\n })\r\n }\r\n </Select>\r\n </FormControl>\r\n </Grid>\r\n </Grid>\r\n </Grid>\r\n )\r\n}\r\n\r\nexport { ObjectSelector }"],"names":["pods","p"],"mappings":";;;;;;;AAiBM,MAAA,cAAA,GAAiB,CAAC,KAAkB,KAAA;AACtC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAC1C,EAAI,IAAA,IAAA,GAAO,MAAM,OAAQ,CAAA,IAAA;AACzB,EAAI,IAAA,aAAA,GAAgB,KAAM,CAAA,IAAA,CAAK,IAAI,GAAA,CAAI,IAAK,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA,CAAA,CAAE,SAAS,CAAC,CAAC,CAAA;AAElE,EAAM,MAAA,iBAAA,GAAoB,CAAC,SAAqB,KAAA;AAC5C,IAAA,IAAI,CAAI,GAAA,KAAA,CAAM,kBAAmB,CAAA,OAAA,CAAQ,SAAS,CAAA;AAClD,IAAA,IAAI,CAAG,IAAA,CAAA;AACH,MAAM,KAAA,CAAA,kBAAA,CAAmB,MAAO,CAAA,CAAA,EAAE,CAAC,CAAA;AAAA;AAEnC,MAAM,KAAA,CAAA,kBAAA,CAAmB,KAAK,SAAS,CAAA;AAE3C,IAAA,KAAA,CAAM,gBAAiB,CAAA,MAAA,CAAO,CAAE,EAAA,KAAA,CAAM,iBAAiB,MAAM,CAAA;AAC7D,IAAA,IAAIA,QAAO,UAAW,EAAA;AACtB,IAAA,IAAIA,KAAK,CAAA,MAAA,KAAS,CAAG,EAAA,KAAA,CAAM,gBAAiB,CAAA,IAAA,CAAM,GAAGA,KAAAA,CAAK,GAAI,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,IAAI,CAAE,CAAA;AAE3E,IAAA,KAAA,CAAM,sBAAuB,CAAA,MAAA,CAAO,CAAE,EAAA,KAAA,CAAM,uBAAuB,MAAM,CAAA;AACzE,IAAA,IAAI,aAAa,gBAAiB,EAAA;AAClC,IAAI,IAAA,UAAA,CAAW,WAAS,CAAG,EAAA;AACvB,MAAM,KAAA,CAAA,sBAAA,CAAuB,IAAK,CAAA,GAAG,UAAU,CAAA;AAC/C,MAAA,KAAA,CAAM,QAAS,CAAA,CAAC,GAAG,KAAA,CAAM,kBAAkB,CAAG,EAAA,CAAC,GAAG,KAAA,CAAM,gBAAgB,CAAG,EAAA,CAAC,GAAG,KAAA,CAAM,sBAAsB,CAAC,CAAA;AAAA;AAGhH,IAAA,SAAA,CAAU,CAAC,MAAM,CAAA;AAAA,GACrB;AAEA,EAAM,MAAA,eAAA,GAAkB,CAAC,KAAgB,KAAA;AACrC,IAAA,KAAA,CAAM,gBAAiB,CAAA,MAAA,CAAO,CAAE,EAAA,KAAA,CAAM,iBAAiB,MAAM,CAAA;AAC7D,IAAA,KAAA,CAAM,gBAAiB,CAAA,IAAA,CAAM,GAAG,KAAA,CAAM,OAAO,KAAM,CAAA;AAEnD,IAAA,KAAA,CAAM,sBAAuB,CAAA,MAAA,CAAO,CAAE,EAAA,KAAA,CAAM,uBAAuB,MAAM,CAAA;AACzE,IAAA,IAAI,aAAa,gBAAiB,EAAA;AAClC,IAAA,IAAI,WAAW,MAAS,KAAA,CAAA,QAAS,sBAAuB,CAAA,IAAA,CAAK,GAAG,UAAU,CAAA;AAE1E,IAAA,KAAA,CAAM,QAAS,CAAA,CAAC,GAAG,KAAA,CAAM,kBAAkB,CAAG,EAAA,CAAC,GAAG,KAAA,CAAM,gBAAgB,CAAG,EAAA,CAAC,GAAG,KAAA,CAAM,sBAAsB,CAAC,CAAA;AAE5G,IAAA,SAAA,CAAU,CAAC,MAAM,CAAA;AAAA,GACrB;AAEA,EAAM,MAAA,qBAAA,GAAwB,CAAC,KAAgB,KAAA;AAC3C,IAAA,KAAA,CAAM,sBAAuB,CAAA,MAAA,CAAO,CAAE,EAAA,KAAA,CAAM,uBAAuB,MAAM,CAAA;AACzE,IAAA,KAAA,CAAM,sBAAuB,CAAA,IAAA,CAAM,GAAG,KAAA,CAAM,OAAO,KAAM,CAAA;AACzD,IAAA,KAAA,CAAM,QAAS,CAAA,CAAC,GAAG,KAAA,CAAM,kBAAkB,CAAG,EAAA,CAAC,GAAG,KAAA,CAAM,gBAAgB,CAAG,EAAA,CAAC,GAAG,KAAA,CAAM,sBAAsB,CAAC,CAAA;AAAA,GAChH;AAEA,EAAM,MAAA,cAAA,GAAiB,CAAC,SAAqB,KAAA;AACzC,IAAI,IAAA,CAAC,MAAM,OAAQ,CAAA,UAAA,CAAW,IAAI,uBAAwB,CAAA,IAAI,GAAU,OAAA,KAAA;AACxE,IAAA,IAAI,YAAY,KAAM,CAAA,OAAA,CAAQ,UAAW,CAAA,GAAA,CAAI,wBAAwB,IAAI,CAAA;AACzE,IAAA,IAAI,SAAW,EAAA;AACX,MAAI,IAAA,SAAA,GAAY,cAAe,CAAA,SAAA,EAAW,QAAQ,CAAA;AAClD,MAAA,OAAQ,SAAU,CAAA,IAAA,CAAK,CAAK,CAAA,KAAA,CAAA,CAAE,cAAc,SAAS,CAAA;AAAA,WAE7C,OAAA,KAAA;AAAA,GAEhB;AAEA,EAAA,MAAM,aAAa,MAAM;AACrB,IAAO,OAAA,KAAA,CAAM,IAAK,CAAA,IAAA,CAAK,MAAO,CAAA,CAAA,CAAA,KAAK,KAAM,CAAA,kBAAA,CAAmB,QAAS,CAAA,CAAA,CAAE,SAAS,CAAC,CAAC,CAAA;AAAA,GACtF;AAEA,EAAA,MAAM,mBAAmB,MAAM;AAC3B,IAAI,IAAA,KAAA,CAAM,mBAAmB,MAAS,KAAA,CAAA,IAAK,MAAM,gBAAiB,CAAA,MAAA,KAAS,CAAG,EAAA,OAAO,EAAC;AACtF,IAAI,IAAA,SAAA,GAAY,KAAK,MAAO,CAAA,CAAA,GAAA,KAAO,MAAM,kBAAmB,CAAA,QAAA,CAAS,GAAI,CAAA,SAAS,CAAC,CAAA;AACnF,IAAY,SAAA,GAAA,SAAA,CAAU,OAAO,CAAAC,EAAAA,KAAK,MAAM,gBAAiB,CAAA,QAAA,CAASA,EAAE,CAAA,IAAI,CAAC,CAAA;AACzE,IAAA,IAAI,kBAA2B,EAAC;AAChC,IAAA,KAAA,IAAS,KAAK,SAAW,EAAA;AACrB,MAAgB,eAAA,CAAA,IAAA,CAAO,GAAG,CAAA,CAAE,UAAW,CAAA;AAAA;AAE3C,IAAA,OAAO,KAAM,CAAA,IAAA,CAAK,IAAI,GAAA,CAAI,eAAe,CAAC,CAAA;AAAA,GAC9C;AAEA,EACI,uBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,SAAS,EAAA,IAAA,EAAC,WAAU,QAAS,EAAA,OAAA,EAAS,CAAG,EAAA,KAAA,EAAO,EAAC,YAAA,EAAa,GAAG,KAAM,EAAA,MAAA,EACzE,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAI,QAEF,aAAc,CAAA,GAAA,CAAK,CAAC,EAAA,EAAG,KAAU,KAAA;AAC7B,IAAA,IAAI,MAAM,QAAU,EAAA;AAChB,MAAA,IAAI,eAAe,EAAE,CAAA;AACjB,QAAA,2CAAQ,IAAK,EAAA,EAAA,SAAA,EAAW,QAAQ,GAAK,EAAA,KAAA,EAAO,OAAO,EAAc,EAAA,OAAA,EAAS,MAAM,kBAAmB,CAAA,QAAA,CAAS,EAAE,CAAE,GAAA,SAAA,GAAU,YAAY,IAAK,EAAA,OAAA,EAAQ,OAAM,SAAU,EAAA,CAAA;AAAA;AAEnK,QAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,SAAW,EAAA,MAAA,EAAQ,GAAK,EAAA,KAAA,EAAO,KAAO,EAAA,EAAA,EAAc,IAAK,EAAA,OAAA,EAAQ,KAAM,EAAA,SAAA,EAAU,SAAS,UAAW,EAAA,CAAA;AAAA,KAErH,MAAA;AACD,MAAA,IAAI,eAAe,EAAE,CAAA;AACjB,QAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,SAAA,EAAW,MAAQ,EAAA,GAAA,EAAK,OAAO,KAAO,EAAA,EAAA,EAAc,OAAS,EAAA,MAAM,iBAAkB,CAAA,EAAE,GAAG,OAAS,EAAA,KAAA,CAAM,kBAAmB,CAAA,QAAA,CAAS,EAAE,CAAA,GAAE,YAAU,UAAY,EAAA,IAAA,EAAK,OAAQ,EAAA,KAAA,EAAM,SAAU,EAAA,CAAA;AAAA;AAEzM,QAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,SAAW,EAAA,MAAA,EAAQ,GAAK,EAAA,KAAA,EAAO,KAAO,EAAA,EAAA,EAAc,IAAK,EAAA,OAAA,EAAQ,KAAM,EAAA,WAAA,EAAY,SAAS,UAAW,EAAA,CAAA;AAAA;AAC5H,GACH,CAET,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,SAAS,EAAA,IAAA,EAAC,IAAI,EAAA,IAAA,EAAC,EAAI,EAAA,EAAA,EAAI,OAAS,EAAA,CAAA,EAAA,kBACjC,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,IAAI,EAAA,IAAA,EAAC,EAAI,EAAA,CAAA,EAAA,kBACV,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAY,IAAK,EAAA,OAAA,EAAQ,SAAS,EAAA,IAAA,EAAA,kBAC1B,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,KAAO,EAAA,KAAA,CAAM,gBAAkB,EAAA,KAAA,kBAAQ,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,IAAM,CAAI,EAAA,QAAA,EAAQ,IAAC,EAAA,QAAA,EAAU,eAAiB,EAAA,WAAA,EAAa,CAAC,QAAA,KAAc,QAAsB,CAAA,IAAA,CAAK,IAAI,CAAA,EAAG,QAAU,EAAA,KAAA,CAAM,QAAY,IAAA,KAAA,CAAM,kBAAmB,CAAA,MAAA,KAAS,CAAK,IAAA,UAAA,EAAa,CAAA,MAAA,KAAS,CAE5O,EAAA,EAAA,UAAA,EAAa,CAAA,GAAA,CAAI,CAAO,GAAA,KAAA;AACpB,IACI,uBAAA,KAAA,CAAA,aAAA,CAAC,YAAS,GAAK,EAAA,GAAA,CAAI,MAAM,KAAO,EAAA,GAAA,CAAI,IAChC,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAS,EAAA,EAAA,OAAA,EAAS,MAAM,gBAAiB,CAAA,QAAA,CAAS,GAAI,CAAA,IAAI,CAAG,EAAA,CAAA,sCAC7D,YAAa,EAAA,EAAA,OAAA,EAAS,GAAI,CAAA,IAAA,EAAM,CACrC,CAAA;AAAA,GAEP,CAET,CACJ,CACR,mBACC,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,MAAI,IAAC,EAAA,EAAA,EAAI,qBACV,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAY,MAAK,OAAQ,EAAA,SAAA,EAAS,wBAC9B,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,KAAO,EAAA,KAAA,CAAM,sBAAwB,EAAA,QAAA,EAAQ,MAAC,QAAU,EAAA,qBAAA,EAAuB,aAAa,CAAC,QAAA,KAAc,SAAsB,IAAK,CAAA,IAAI,CAAG,EAAA,QAAA,EAAU,KAAM,CAAA,QAAA,IAAY,MAAM,gBAAiB,CAAA,MAAA,KAAS,KAAK,gBAAiB,EAAA,CAAE,WAAS,CAE1O,EAAA,EAAA,gBAAA,EAAmB,CAAA,GAAA,CAAI,CAAa,SAAA,KAAA;AAChC,IAAA,2CACK,QAAS,EAAA,EAAA,GAAA,EAAK,WAAW,KAAO,EAAA,SAAA,EAAA,sCAC5B,QAAS,EAAA,EAAA,OAAA,EAAS,MAAM,sBAAuB,CAAA,QAAA,CAAS,SAAS,CAAG,EAAA,CAAA,sCACpE,YAAa,EAAA,EAAA,OAAA,EAAS,WAAW,CACtC,CAAA;AAAA,GAEP,CAET,CACJ,CACJ,CACJ,CACJ,CAAA;AAER;;;;"}
|
|
1
|
+
{"version":3,"file":"ObjectSelector.esm.js","sources":["../../../src/components/ObjectSelector/ObjectSelector.tsx"],"sourcesContent":["import React, { useState } from 'react'\r\nimport { ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\nimport FormControl from '@material-ui/core/FormControl'\r\nimport Select from '@material-ui/core/Select'\r\nimport MenuItem from '@material-ui/core/MenuItem'\r\nimport { Checkbox, Chip, Grid, ListItemText } from '@material-ui/core'\r\nimport { InstanceConfigScopeEnum, parseResources } from '@jfvilas/kwirth-common'\r\n\r\ninterface IProps {\r\n onSelect: (namespaces:string[], podNames:string[], containerNames:string[]) => void,\r\n cluster: ClusterValidPods,\r\n selectedNamespaces: string[],\r\n selectedPodNames: string[],\r\n selectedContainerNames: string[],\r\n disabled: boolean\r\n}\r\n\r\nconst ObjectSelector = (props: IProps) => {\r\n const [render, setRender] = useState(false)\r\n let pods = props.cluster.data\r\n let namespaceList = Array.from(new Set(pods.map(p => p.namespace)))\r\n\r\n const onNamespaceChange = (namespace:string) => {\r\n let i = props.selectedNamespaces.indexOf(namespace)\r\n if (i>=0)\r\n props.selectedNamespaces.splice(i,1)\r\n else\r\n props.selectedNamespaces.push(namespace)\r\n\r\n props.selectedPodNames.splice(0,props.selectedPodNames.length)\r\n let pods = getPodList()\r\n if (pods.length===1) props.selectedPodNames.push( ...pods.map(p => p.name) )\r\n\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n let containers = getContainerList()\r\n if (containers.length===1) {\r\n props.selectedContainerNames.push(...containers)\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n }\r\n\r\n setRender(!render)\r\n };\r\n\r\n const onPodNameChange = (event : any) => {\r\n props.selectedPodNames.splice(0,props.selectedPodNames.length)\r\n props.selectedPodNames.push( ...event.target.value )\r\n\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n let containers = getContainerList()\r\n if (containers.length===1) props.selectedContainerNames.push(...containers)\r\n\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n\r\n setRender(!render)\r\n };\r\n\r\n const onContainerNameChange = (event : any) => {\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n props.selectedContainerNames.push( ...event.target.value )\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n };\r\n\r\n const existAccessKey = (namespace:string) => {\r\n if (!props.cluster.accessKeys.has(InstanceConfigScopeEnum.VIEW)) return false\r\n let accessKey = props.cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW)\r\n if (accessKey) {\r\n let resources = parseResources(accessKey.resources)\r\n return (resources.find(resource => resource.namespaces === namespace))\r\n }\r\n else return false\r\n\r\n }\r\n\r\n const getPodList = () => {\r\n return Array.from(pods.filter(m => props.selectedNamespaces.includes(m.namespace)))\r\n }\r\n\r\n const getContainerList = () => {\r\n if (props.selectedNamespaces.length===0 || props.selectedPodNames.length===0) return []\r\n let validpods = pods.filter(pod => props.selectedNamespaces.includes(pod.namespace))\r\n validpods = validpods.filter(p => props.selectedPodNames.includes(p.name))\r\n let validcontainers:string[] = []\r\n for (var p of validpods) {\r\n validcontainers.push ( ...p.containers )\r\n }\r\n return Array.from(new Set(validcontainers))\r\n }\r\n\r\n return (\r\n <Grid container direction='column' spacing={0} style={{marginBottom:6, width:'100%'}}>\r\n <Grid item>\r\n {\r\n namespaceList.map ((ns,index) => {\r\n if (props.disabled) {\r\n if (existAccessKey(ns))\r\n return <Chip component={'span'} key={index} label={ns as string} variant={props.selectedNamespaces.includes(ns)?'default':'outlined'} size='small' color='default' />\r\n else\r\n return <Chip component={'span'} key={index} label={ns as string} size='small' color='default' variant={'outlined'}/>\r\n }\r\n else {\r\n if (existAccessKey(ns))\r\n return <Chip component={'span'} key={index} label={ns as string} onClick={() => onNamespaceChange(ns)} variant={props.selectedNamespaces.includes(ns)?'default':'outlined'} size='small' color='primary' />\r\n else\r\n return <Chip component={'span'} key={index} label={ns as string} size='small' color='secondary' variant={'outlined'}/>\r\n }\r\n })\r\n }\r\n </Grid>\r\n <Grid container item xs={12} spacing={2}>\r\n <Grid item xs={6}>\r\n <FormControl size='small' fullWidth>\r\n <Select value={props.selectedPodNames} MenuProps={{variant:'menu'}} multiple onChange={onPodNameChange} renderValue={(selected) => (selected as string[]).join(', ')} disabled={props.disabled || props.selectedNamespaces.length===0 || getPodList().length===1}>\r\n {\r\n getPodList().map(pod => {\r\n return (\r\n <MenuItem key={pod.name} value={pod.name}>\r\n <Checkbox checked={props.selectedPodNames.includes(pod.name)} />\r\n <ListItemText primary={pod.name} />\r\n </MenuItem>\r\n )\r\n })\r\n }\r\n </Select>\r\n </FormControl>\r\n </Grid>\r\n <Grid item xs={6}>\r\n <FormControl size='small' fullWidth>\r\n <Select value={props.selectedContainerNames} MenuProps={{variant:'menu'}} multiple onChange={onContainerNameChange} renderValue={(selected) => (selected as string[]).join(', ')} disabled={props.disabled || props.selectedPodNames.length===0 || getContainerList().length===1}>\r\n {\r\n getContainerList().map(container => {\r\n return (\r\n <MenuItem key={container} value={container}>\r\n <Checkbox checked={props.selectedContainerNames.includes(container)} />\r\n <ListItemText primary={container} />\r\n </MenuItem>\r\n )\r\n })\r\n }\r\n </Select>\r\n </FormControl>\r\n </Grid>\r\n </Grid>\r\n </Grid>\r\n )\r\n}\r\n\r\nexport { ObjectSelector }"],"names":["pods","p"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { Dialog, DialogTitle, DialogContent, Typography, DialogActions, Button }
|
|
|
3
3
|
import { InstanceMessageTypeEnum } from '@jfvilas/kwirth-common';
|
|
4
4
|
|
|
5
5
|
const StatusLog = (props) => {
|
|
6
|
-
return /* @__PURE__ */ React.createElement(Dialog, { open: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "Stauts: ", props.level), /* @__PURE__ */ React.createElement(DialogContent, null, props.statusMessages.filter((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === props.level).map((m, index) => /* @__PURE__ */ React.createElement(Typography, { key: index }, m.
|
|
6
|
+
return /* @__PURE__ */ React.createElement(Dialog, { open: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "Stauts: ", props.level), /* @__PURE__ */ React.createElement(DialogContent, null, props.statusMessages.filter((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === props.level).map((m, index) => /* @__PURE__ */ React.createElement(Typography, { key: index }, m.text))), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(Button, { onClick: () => props.onClear(props.level), color: "primary", variant: "contained" }, "Clear"), /* @__PURE__ */ React.createElement(Button, { onClick: props.onClose, color: "primary", variant: "contained" }, "Close")));
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export { StatusLog };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusLog.esm.js","sources":["../../../src/components/StatusLog/StatusLog.tsx"],"sourcesContent":["import React from 'react';\r\nimport { Dialog, DialogTitle, DialogContent, DialogActions, Button, Typography } from '@material-ui/core'\r\nimport { InstanceMessageTypeEnum,
|
|
1
|
+
{"version":3,"file":"StatusLog.esm.js","sources":["../../../src/components/StatusLog/StatusLog.tsx"],"sourcesContent":["import React from 'react';\r\nimport { Dialog, DialogTitle, DialogContent, DialogActions, Button, Typography } from '@material-ui/core'\r\nimport { InstanceMessageTypeEnum, SignalMessageLevelEnum } from '@jfvilas/kwirth-common'\r\nimport { IStatusLine } from '@jfvilas/plugin-kwirth-common';\r\n\r\ninterface IProps {\r\n level: SignalMessageLevelEnum\r\n statusMessages: IStatusLine[]\r\n onClear: (level:SignalMessageLevelEnum) => void\r\n onClose: () => void\r\n}\r\n\r\nconst StatusLog = (props:IProps) => {\r\n return (\r\n <Dialog open={true}>\r\n <DialogTitle>\r\n Stauts: {props.level} \r\n </DialogTitle>\r\n <DialogContent>\r\n { props.statusMessages.filter(m => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === props.level).map( (m,index) => <Typography key={index}>{m.text}</Typography>) }\r\n </DialogContent>\r\n <DialogActions>\r\n <Button onClick={() => props.onClear(props.level)} color='primary' variant='contained'>Clear</Button>\r\n <Button onClick={props.onClose} color='primary' variant='contained'>Close</Button>\r\n </DialogActions>\r\n </Dialog>\r\n )\r\n\r\n}\r\n\r\nexport { StatusLog }"],"names":[],"mappings":";;;;AAYM,MAAA,SAAA,GAAY,CAAC,KAAiB,KAAA;AAChC,EAAA,uBACK,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,IAAM,EAAA,IAAA,EAAA,kBACT,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,IAAA,EAAY,UACA,EAAA,KAAA,CAAM,KACnB,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,IAAA,EACK,MAAM,cAAe,CAAA,MAAA,CAAO,CAAK,CAAA,KAAA,CAAA,CAAE,IAAS,KAAA,uBAAA,CAAwB,MAAU,IAAA,CAAA,CAAE,UAAU,KAAM,CAAA,KAAK,CAAE,CAAA,GAAA,CAAK,CAAC,CAAA,EAAE,KAAU,qBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,GAAK,EAAA,KAAA,EAAA,EAAQ,CAAE,CAAA,IAAK,CAAa,CAC5K,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,aACG,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,MAAO,EAAA,EAAA,OAAA,EAAS,MAAM,KAAA,CAAM,OAAQ,CAAA,KAAA,CAAM,KAAK,CAAG,EAAA,KAAA,EAAM,SAAU,EAAA,OAAA,EAAQ,WAAY,EAAA,EAAA,OAAK,CAC5F,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAO,OAAS,EAAA,KAAA,CAAM,OAAS,EAAA,KAAA,EAAM,SAAU,EAAA,OAAA,EAAQ,WAAY,EAAA,EAAA,OAAK,CAC7E,CACJ,CAAA;AAGR;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import * as react from 'react';
|
|
2
3
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
3
4
|
import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
|
|
@@ -8,7 +9,9 @@ import { ClusterValidPods } from '@jfvilas/plugin-kwirth-common';
|
|
|
8
9
|
declare const kwirthLogPlugin: _backstage_core_plugin_api.BackstagePlugin<{
|
|
9
10
|
root: _backstage_core_plugin_api.RouteRef<undefined>;
|
|
10
11
|
}, {}, {}>;
|
|
11
|
-
declare const EntityKwirthLogContent: (
|
|
12
|
+
declare const EntityKwirthLogContent: (props: {
|
|
13
|
+
enableRestart: boolean;
|
|
14
|
+
}) => react.JSX.Element;
|
|
12
15
|
|
|
13
16
|
interface KwirthLogApi {
|
|
14
17
|
getResources(entity: Entity): Promise<any>;
|
package/dist/plugin.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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 { kwirthLogApiRef, KwirthLogClient } from './api';\r\nimport { createApiFactory, createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';\r\nimport { discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';\r\nimport { rootRouteRef } from './routes';\r\n\r\nexport const kwirthLogPlugin = createPlugin({\r\n id: 'kwirthlog', \r\n apis: [\r\n createApiFactory({\r\n api: kwirthLogApiRef,\r\n deps: {\r\n discoveryApi: discoveryApiRef,\r\n fetchApi: fetchApiRef,\r\n },\r\n factory({ discoveryApi, fetchApi }) {\r\n return new KwirthLogClient({ discoveryApi, fetchApi });\r\n },\r\n }),\r\n ],\r\n routes: {\r\n root: rootRouteRef\r\n }\r\n})
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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\n\r\nimport { kwirthLogApiRef, KwirthLogClient } from './api';\r\nimport { createApiFactory, createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';\r\nimport { discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';\r\nimport { rootRouteRef } from './routes';\r\n\r\nexport const kwirthLogPlugin = createPlugin({\r\n id: 'kwirthlog', \r\n apis: [\r\n createApiFactory({\r\n api: kwirthLogApiRef,\r\n deps: {\r\n discoveryApi: discoveryApiRef,\r\n fetchApi: fetchApiRef,\r\n },\r\n factory({ discoveryApi, fetchApi }) {\r\n return new KwirthLogClient({ discoveryApi, fetchApi });\r\n },\r\n }),\r\n ],\r\n routes: {\r\n root: rootRouteRef\r\n }\r\n})\r\n\r\nexport const EntityKwirthLogContent = kwirthLogPlugin.provide(\r\n createRoutableExtension({\r\n name: 'EntityKwirthLogContent',\r\n component: () =>\r\n import('./components/EntityKwirthLogContent').then(m => m.EntityKwirthLogContent),\r\n mountPoint: rootRouteRef\r\n })\r\n)\r\n"],"names":[],"mappings":";;;;;AAqBO,MAAM,kBAAkB,YAAa,CAAA;AAAA,EAC1C,EAAI,EAAA,WAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,eAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,YAAc,EAAA,eAAA;AAAA,QACd,QAAU,EAAA;AAAA,OACZ;AAAA,MACA,OAAQ,CAAA,EAAE,YAAc,EAAA,QAAA,EAAY,EAAA;AAClC,QAAA,OAAO,IAAI,eAAA,CAAgB,EAAE,YAAA,EAAc,UAAU,CAAA;AAAA;AACvD,KACD;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA;AAAA;AAEV,CAAC;AAEM,MAAM,yBAAyB,eAAgB,CAAA,OAAA;AAAA,EACpD,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,wBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,kDAAqC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,sBAAsB,CAAA;AAAA,IAClF,UAAY,EAAA;AAAA,GACb;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jfvilas/plugin-kwirth-log",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.6",
|
|
4
4
|
"description": "Frontend plugin for viewing real-time Kubernetes logs in Backstage",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Backstage",
|
|
@@ -63,7 +63,6 @@
|
|
|
63
63
|
"@backstage/integration-react": "^1.1.29",
|
|
64
64
|
"@backstage/plugin-auth-react": "^0.1.4",
|
|
65
65
|
"@backstage/plugin-catalog-react": "^1.12.2",
|
|
66
|
-
"@jfvilas/kwirth-common": "^0.3.55",
|
|
67
66
|
"@material-ui/core": "^4.12.2",
|
|
68
67
|
"@material-ui/icons": "^4.9.1",
|
|
69
68
|
"@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import IconButton from '@material-ui/core/IconButton';
|
|
3
|
-
import Snackbar from '@material-ui/core/Snackbar';
|
|
4
|
-
import CloseIcon from '@material-ui/icons/Close';
|
|
5
|
-
|
|
6
|
-
const ShowError = (props) => {
|
|
7
|
-
return /* @__PURE__ */ React.createElement(
|
|
8
|
-
Snackbar,
|
|
9
|
-
{
|
|
10
|
-
message: `An error has ocurred: ${props.message}`,
|
|
11
|
-
open: true,
|
|
12
|
-
autoHideDuration: 3e3,
|
|
13
|
-
anchorOrigin: { vertical: "top", horizontal: "center" },
|
|
14
|
-
action: /* @__PURE__ */ React.createElement(IconButton, { size: "small", "aria-label": "close", color: "inherit", onClick: props.onClose }, /* @__PURE__ */ React.createElement(CloseIcon, { fontSize: "small" }))
|
|
15
|
-
}
|
|
16
|
-
);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export { ShowError };
|
|
20
|
-
//# sourceMappingURL=ShowError.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ShowError.esm.js","sources":["../../../src/components/ShowError/ShowError.tsx"],"sourcesContent":["import React from 'react'\r\nimport IconButton from '@material-ui/core/IconButton'\r\nimport Snackbar from '@material-ui/core/Snackbar'\r\nimport CloseIcon from '@material-ui/icons/Close'\r\n\r\nconst ShowError = (props: {\r\n message: string\r\n onClose:() => void\r\n }) => {\r\n\r\n return (\r\n <Snackbar \r\n message={`An error has ocurred: ${props.message}`}\r\n open={true}\r\n autoHideDuration={3000}\r\n anchorOrigin={{ vertical:'top', horizontal:'center' }}\r\n action={ \r\n <IconButton size=\"small\" aria-label=\"close\" color=\"inherit\" onClick={props.onClose}>\r\n <CloseIcon fontSize=\"small\" />\r\n </IconButton>\r\n }>\r\n </Snackbar>\r\n )\r\n}\r\n\r\nexport { ShowError }"],"names":[],"mappings":";;;;;AAKM,MAAA,SAAA,GAAY,CAAC,KAGT,KAAA;AAEN,EACI,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACG,OAAA,EAAS,CAAyB,sBAAA,EAAA,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,MAC/C,IAAM,EAAA,IAAA;AAAA,MACN,gBAAkB,EAAA,GAAA;AAAA,MAClB,YAAc,EAAA,EAAE,QAAS,EAAA,KAAA,EAAO,YAAW,QAAS,EAAA;AAAA,MACpD,wBACK,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,IAAK,EAAA,OAAA,EAAQ,cAAW,OAAQ,EAAA,KAAA,EAAM,SAAU,EAAA,OAAA,EAAS,MAAM,OACvE,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,SAAU,EAAA,EAAA,QAAA,EAAS,SAAQ,CAChC;AAAA;AAAA,GAER;AAER;;;;"}
|