@backstage/plugin-kubernetes 0.10.4-next.0 → 0.11.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,402 +1,12 @@
1
- import { stringifyEntityRef } from '@backstage/catalog-model';
2
- import { NotFoundError } from '@backstage/errors';
3
- import { createApiRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef, identityApiRef, gitlabAuthApiRef, googleAuthApiRef, microsoftAuthApiRef, oktaAuthApiRef, oneloginAuthApiRef, createRoutableExtension, useApi } from '@backstage/core-plugin-api';
4
- import * as React from 'react';
5
- import React__default, { useCallback, useContext, useState, useEffect, useMemo, Fragment } from 'react';
1
+ import { kubernetesApiRef, kubernetesAuthProvidersApiRef, KubernetesBackendClient, kubernetesProxyApiRef, KubernetesProxyClient, KubernetesAuthProviders, useKubernetesObjects, DetectedErrorsContext, ErrorPanel, ErrorReporting, Cluster } from '@backstage/plugin-kubernetes-react';
2
+ export * from '@backstage/plugin-kubernetes-react';
3
+ import { createRouteRef, createPlugin, createApiFactory, discoveryApiRef, identityApiRef, gitlabAuthApiRef, googleAuthApiRef, microsoftAuthApiRef, oktaAuthApiRef, oneloginAuthApiRef, createRoutableExtension } from '@backstage/core-plugin-api';
4
+ import React from 'react';
6
5
  import { useEntity } from '@backstage/plugin-catalog-react';
7
6
  import { Routes, Route } from 'react-router-dom';
8
- import { Typography, makeStyles, createStyles, Dialog, DialogTitle, IconButton, DialogContent, Button, Grid, Paper, Card, CardHeader, CardContent, CardActions, FormControlLabel, Switch, Drawer, withStyles as withStyles$1, List, ListItem, Container, Tooltip, ListItemText, ListItemAvatar, Avatar, Divider, Chip, Accordion, AccordionSummary, AccordionDetails, Stepper, Step, StepLabel } from '@material-ui/core';
9
- import { WarningPanel, Table, LinearGauge, DismissableBanner, EmptyState, LogViewer, StructuredMetadataTable, CodeSnippet, LinkButton, StatusError, StatusOK, StatusWarning, ItemCardGrid, SubvalueCell, StatusAborted, StatusPending, Page, Content, Progress, MissingAnnotationEmptyState } from '@backstage/core-components';
10
- import lodash from 'lodash';
11
- import { DateTime } from 'luxon';
12
- import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
13
- import CloseIcon from '@material-ui/icons/Close';
14
- import OpenInBrowserIcon from '@material-ui/icons/OpenInBrowser';
15
- import useAsync from 'react-use/lib/useAsync';
16
- import useInterval from 'react-use/lib/useInterval';
17
- import useAsyncRetry from 'react-use/lib/useAsyncRetry';
18
- import 'xterm/css/xterm.css';
19
- import { Terminal } from 'xterm';
20
- import { FitAddon } from 'xterm-addon-fit';
21
- import { AttachAddon } from 'xterm-addon-attach';
22
- import { Skeleton } from '@material-ui/lab';
23
- import SubjectIcon from '@material-ui/icons/Subject';
24
- import OpenInNewIcon from '@material-ui/icons/OpenInNew';
25
- import { withStyles, makeStyles as makeStyles$1, createStyles as createStyles$1 } from '@material-ui/core/styles';
26
- import jsyaml from 'js-yaml';
27
- import Dialog$1 from '@material-ui/core/Dialog';
28
- import DialogActions from '@material-ui/core/DialogActions';
29
- import DialogContent$1 from '@material-ui/core/DialogContent';
30
- import DialogTitle$1 from '@material-ui/core/DialogTitle';
31
- import IconButton$1 from '@material-ui/core/IconButton';
32
- import Typography$1 from '@material-ui/core/Typography';
33
- import HelpIcon from '@material-ui/icons/Help';
34
- import InfoIcon from '@material-ui/icons/Info';
35
- import WarningIcon from '@material-ui/icons/Warning';
36
- import cronstrue from 'cronstrue';
37
- import PauseIcon from '@material-ui/icons/Pause';
38
- import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
39
- import EmptyStateImage from './assets/emptystate.svg';
40
-
41
- var __defProp$4 = Object.defineProperty;
42
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
43
- var __publicField$4 = (obj, key, value) => {
44
- __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
45
- return value;
46
- };
47
- class KubernetesBackendClient {
48
- constructor(options) {
49
- __publicField$4(this, "discoveryApi");
50
- __publicField$4(this, "identityApi");
51
- __publicField$4(this, "kubernetesAuthProvidersApi");
52
- this.discoveryApi = options.discoveryApi;
53
- this.identityApi = options.identityApi;
54
- this.kubernetesAuthProvidersApi = options.kubernetesAuthProvidersApi;
55
- }
56
- async handleResponse(response) {
57
- if (!response.ok) {
58
- const payload = await response.text();
59
- let message;
60
- switch (response.status) {
61
- case 404:
62
- message = "Could not find the Kubernetes Backend (HTTP 404). Make sure the plugin has been fully installed.";
63
- break;
64
- default:
65
- message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
66
- }
67
- throw new Error(message);
68
- }
69
- return await response.json();
70
- }
71
- async postRequired(path, requestBody) {
72
- const url = `${await this.discoveryApi.getBaseUrl("kubernetes")}${path}`;
73
- const { token: idToken } = await this.identityApi.getCredentials();
74
- const response = await fetch(url, {
75
- method: "POST",
76
- headers: {
77
- "Content-Type": "application/json",
78
- ...idToken && { Authorization: `Bearer ${idToken}` }
79
- },
80
- body: JSON.stringify(requestBody)
81
- });
82
- return this.handleResponse(response);
83
- }
84
- async getCluster(clusterName) {
85
- const cluster = await this.getClusters().then(
86
- (clusters) => clusters.find((c) => c.name === clusterName)
87
- );
88
- if (!cluster) {
89
- throw new NotFoundError(`Cluster ${clusterName} not found`);
90
- }
91
- return cluster;
92
- }
93
- async getCredentials(authProvider) {
94
- return await this.kubernetesAuthProvidersApi.getCredentials(authProvider);
95
- }
96
- async getObjectsByEntity(requestBody) {
97
- return await this.postRequired(
98
- `/services/${requestBody.entity.metadata.name}`,
99
- requestBody
100
- );
101
- }
102
- async getWorkloadsByEntity(request) {
103
- return await this.postRequired("/resources/workloads/query", {
104
- auth: request.auth,
105
- entityRef: stringifyEntityRef(request.entity)
106
- });
107
- }
108
- async getCustomObjectsByEntity(request) {
109
- return await this.postRequired(`/resources/custom/query`, {
110
- entityRef: stringifyEntityRef(request.entity),
111
- auth: request.auth,
112
- customResources: request.customResources
113
- });
114
- }
115
- async getClusters() {
116
- const { token: idToken } = await this.identityApi.getCredentials();
117
- const url = `${await this.discoveryApi.getBaseUrl("kubernetes")}/clusters`;
118
- const response = await fetch(url, {
119
- method: "GET",
120
- headers: {
121
- ...idToken && { Authorization: `Bearer ${idToken}` }
122
- }
123
- });
124
- return (await this.handleResponse(response)).items;
125
- }
126
- async proxy(options) {
127
- var _a;
128
- const { authProvider } = await this.getCluster(options.clusterName);
129
- const { token: k8sToken } = await this.getCredentials(authProvider);
130
- const url = `${await this.discoveryApi.getBaseUrl("kubernetes")}/proxy${options.path}`;
131
- const identityResponse = await this.identityApi.getCredentials();
132
- const headers = {
133
- ...(_a = options.init) == null ? void 0 : _a.headers,
134
- [`Backstage-Kubernetes-Cluster`]: options.clusterName,
135
- ...k8sToken && {
136
- [`Backstage-Kubernetes-Authorization`]: `Bearer ${k8sToken}`
137
- },
138
- ...identityResponse.token && {
139
- Authorization: `Bearer ${identityResponse.token}`
140
- }
141
- };
142
- return await fetch(url, { ...options.init, headers });
143
- }
144
- }
145
-
146
- const kubernetesApiRef = createApiRef({
147
- id: "plugin.kubernetes.service"
148
- });
149
- const kubernetesProxyApiRef = createApiRef({
150
- id: "plugin.kubernetes.proxy-service"
151
- });
152
-
153
- const kubernetesAuthProvidersApiRef = createApiRef({
154
- id: "plugin.kubernetes-auth-providers.service"
155
- });
156
-
157
- var __defProp$3 = Object.defineProperty;
158
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
159
- var __publicField$3 = (obj, key, value) => {
160
- __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
161
- return value;
162
- };
163
- class GoogleKubernetesAuthProvider {
164
- constructor(authProvider) {
165
- __publicField$3(this, "authProvider");
166
- this.authProvider = authProvider;
167
- }
168
- async decorateRequestBodyForAuth(requestBody) {
169
- const googleAuthToken = (await this.getCredentials()).token;
170
- if ("auth" in requestBody) {
171
- requestBody.auth.google = googleAuthToken;
172
- } else {
173
- requestBody.auth = { google: googleAuthToken };
174
- }
175
- return requestBody;
176
- }
177
- async getCredentials() {
178
- return {
179
- token: await this.authProvider.getAccessToken(
180
- "https://www.googleapis.com/auth/cloud-platform.read-only"
181
- )
182
- };
183
- }
184
- }
185
-
186
- class ServerSideKubernetesAuthProvider {
187
- async decorateRequestBodyForAuth(requestBody) {
188
- return requestBody;
189
- }
190
- async getCredentials() {
191
- return {};
192
- }
193
- }
194
-
195
- var __defProp$2 = Object.defineProperty;
196
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
197
- var __publicField$2 = (obj, key, value) => {
198
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
199
- return value;
200
- };
201
- class OidcKubernetesAuthProvider {
202
- constructor(providerName, authProvider) {
203
- __publicField$2(this, "providerName");
204
- __publicField$2(this, "authProvider");
205
- this.providerName = providerName;
206
- this.authProvider = authProvider;
207
- }
208
- async decorateRequestBodyForAuth(requestBody) {
209
- const authToken = (await this.getCredentials()).token;
210
- const auth = { ...requestBody.auth };
211
- if (auth.oidc) {
212
- auth.oidc[this.providerName] = authToken;
213
- } else {
214
- auth.oidc = { [this.providerName]: authToken };
215
- }
216
- requestBody.auth = auth;
217
- return requestBody;
218
- }
219
- async getCredentials() {
220
- return {
221
- token: await this.authProvider.getIdToken()
222
- };
223
- }
224
- }
225
-
226
- class AksKubernetesAuthProvider {
227
- constructor(microsoftAuthApi) {
228
- this.microsoftAuthApi = microsoftAuthApi;
229
- }
230
- async decorateRequestBodyForAuth(requestBody) {
231
- return {
232
- ...requestBody,
233
- auth: { ...requestBody.auth, aks: (await this.getCredentials()).token }
234
- };
235
- }
236
- async getCredentials() {
237
- return {
238
- token: await this.microsoftAuthApi.getAccessToken(
239
- "6dae42f8-4368-4678-94ff-3960e28e3630/user.read"
240
- )
241
- };
242
- }
243
- }
244
-
245
- var __defProp$1 = Object.defineProperty;
246
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
247
- var __publicField$1 = (obj, key, value) => {
248
- __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
249
- return value;
250
- };
251
- class KubernetesAuthProviders {
252
- constructor(options) {
253
- __publicField$1(this, "kubernetesAuthProviderMap");
254
- this.kubernetesAuthProviderMap = /* @__PURE__ */ new Map();
255
- this.kubernetesAuthProviderMap.set(
256
- "google",
257
- new GoogleKubernetesAuthProvider(options.googleAuthApi)
258
- );
259
- this.kubernetesAuthProviderMap.set(
260
- "serviceAccount",
261
- new ServerSideKubernetesAuthProvider()
262
- );
263
- this.kubernetesAuthProviderMap.set(
264
- "googleServiceAccount",
265
- new ServerSideKubernetesAuthProvider()
266
- );
267
- this.kubernetesAuthProviderMap.set(
268
- "aws",
269
- new ServerSideKubernetesAuthProvider()
270
- );
271
- this.kubernetesAuthProviderMap.set(
272
- "azure",
273
- new ServerSideKubernetesAuthProvider()
274
- );
275
- this.kubernetesAuthProviderMap.set(
276
- "localKubectlProxy",
277
- new ServerSideKubernetesAuthProvider()
278
- );
279
- this.kubernetesAuthProviderMap.set(
280
- "aks",
281
- new AksKubernetesAuthProvider(options.microsoftAuthApi)
282
- );
283
- if (options.oidcProviders) {
284
- Object.keys(options.oidcProviders).forEach((provider) => {
285
- this.kubernetesAuthProviderMap.set(
286
- `oidc.${provider}`,
287
- new OidcKubernetesAuthProvider(
288
- provider,
289
- options.oidcProviders[provider]
290
- )
291
- );
292
- });
293
- }
294
- }
295
- async decorateRequestBodyForAuth(authProvider, requestBody) {
296
- const kubernetesAuthProvider = this.kubernetesAuthProviderMap.get(authProvider);
297
- if (kubernetesAuthProvider) {
298
- return await kubernetesAuthProvider.decorateRequestBodyForAuth(
299
- requestBody
300
- );
301
- }
302
- if (authProvider.startsWith("oidc.")) {
303
- throw new Error(
304
- `KubernetesAuthProviders has no oidcProvider configured for ${authProvider}`
305
- );
306
- }
307
- throw new Error(
308
- `authProvider "${authProvider}" has no KubernetesAuthProvider defined for it`
309
- );
310
- }
311
- async getCredentials(authProvider) {
312
- const kubernetesAuthProvider = this.kubernetesAuthProviderMap.get(authProvider);
313
- if (kubernetesAuthProvider) {
314
- return await kubernetesAuthProvider.getCredentials();
315
- }
316
- if (authProvider.startsWith("oidc.")) {
317
- throw new Error(
318
- `KubernetesAuthProviders has no oidcProvider configured for ${authProvider}`
319
- );
320
- }
321
- throw new Error(
322
- `authProvider "${authProvider}" has no KubernetesAuthProvider defined for it`
323
- );
324
- }
325
- }
326
-
327
- var __defProp = Object.defineProperty;
328
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
329
- var __publicField = (obj, key, value) => {
330
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
331
- return value;
332
- };
333
- class KubernetesProxyClient {
334
- constructor(options) {
335
- __publicField(this, "kubernetesApi");
336
- this.kubernetesApi = options.kubernetesApi;
337
- }
338
- async handleText(response) {
339
- if (!response.ok) {
340
- const payload = await response.text();
341
- let message;
342
- switch (response.status) {
343
- default:
344
- message = `Proxy request failed with ${response.status} ${response.statusText}, ${payload}`;
345
- }
346
- throw new Error(message);
347
- }
348
- return await response.text();
349
- }
350
- async handleJson(response) {
351
- if (!response.ok) {
352
- const payload = await response.text();
353
- let message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
354
- switch (response.status) {
355
- case 404:
356
- message = `Proxy request failed with ${response.status} ${response.statusText}, ${payload}`;
357
- break;
358
- default:
359
- message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
360
- }
361
- throw new Error(message);
362
- }
363
- return await response.json();
364
- }
365
- async getEventsByInvolvedObjectName({
366
- clusterName,
367
- involvedObjectName,
368
- namespace
369
- }) {
370
- return await this.kubernetesApi.proxy({
371
- clusterName,
372
- path: `/api/v1/namespaces/${namespace}/events?fieldSelector=involvedObject.name=${involvedObjectName}`,
373
- init: {
374
- method: "GET"
375
- }
376
- }).then((response) => this.handleJson(response)).then((eventList) => eventList.items);
377
- }
378
- async getPodLogs({
379
- podName,
380
- namespace,
381
- clusterName,
382
- containerName,
383
- previous
384
- }) {
385
- const params = new URLSearchParams({
386
- container: containerName
387
- });
388
- if (previous) {
389
- params.append("previous", "");
390
- }
391
- return await this.kubernetesApi.proxy({
392
- clusterName,
393
- path: `/api/v1/namespaces/${namespace}/pods/${podName}/log?${params.toString()}`,
394
- init: {
395
- method: "GET"
396
- }
397
- }).then((response) => this.handleText(response)).then((text) => ({ text }));
398
- }
399
- }
7
+ import { Grid, Typography, Button } from '@material-ui/core';
8
+ import { detectErrors } from '@backstage/plugin-kubernetes-common';
9
+ import { Page, Content, Progress, EmptyState, MissingAnnotationEmptyState } from '@backstage/core-components';
400
10
 
401
11
  const rootCatalogKubernetesRouteRef = createRouteRef({
402
12
  id: "kubernetes"
@@ -469,3224 +79,44 @@ const EntityKubernetesContent = kubernetesPlugin.provide(
469
79
  })
470
80
  );
471
81
 
472
- const clustersWithErrorsToErrorMessage = (clustersWithErrors) => {
473
- return clustersWithErrors.map((c, i) => {
474
- return /* @__PURE__ */ React__default.createElement("div", { key: i }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2" }, `Cluster: ${c.cluster.name}`), c.errors.map((e, j) => {
475
- return /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2", key: j }, e.errorType === "FETCH_ERROR" ? `Error communicating with Kubernetes: ${e.errorType}, message: ${e.message}` : `Error fetching Kubernetes resource: '${e.resourcePath}', error: ${e.errorType}, status code: ${e.statusCode}`);
476
- }), /* @__PURE__ */ React__default.createElement("br", null));
477
- });
478
- };
479
- const ErrorPanel = ({
480
- entityName,
481
- errorMessage,
482
- clustersWithErrors
483
- }) => /* @__PURE__ */ React__default.createElement(
484
- WarningPanel,
485
- {
486
- title: "There was a problem retrieving Kubernetes objects",
487
- message: `There was a problem retrieving some Kubernetes resources for the entity: ${entityName}. This could mean that the Error Reporting card is not completely accurate.`
488
- },
489
- clustersWithErrors && /* @__PURE__ */ React__default.createElement("div", null, "Errors: ", clustersWithErrorsToErrorMessage(clustersWithErrors)),
490
- errorMessage && /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2" }, "Errors: ", errorMessage)
491
- );
492
-
493
- const columns = [
494
- {
495
- title: "cluster",
496
- width: "10%",
497
- render: (row) => row.clusterName
498
- },
499
- {
500
- title: "namespace",
501
- width: "10%",
502
- render: (row) => row.error.sourceRef.namespace
503
- },
504
- {
505
- title: "kind",
506
- width: "10%",
507
- render: (row) => row.error.sourceRef.kind
508
- },
509
- {
510
- title: "name",
511
- width: "30%",
512
- render: (row) => {
513
- return /* @__PURE__ */ React.createElement(React.Fragment, null, row.error.sourceRef.name, " ");
514
- }
515
- },
516
- {
517
- title: "messages",
518
- width: "40%",
519
- render: (row) => row.error.message
520
- }
521
- ];
522
- const sortBySeverity = (a, b) => {
523
- if (a.error.severity < b.error.severity) {
524
- return 1;
525
- } else if (b.error.severity < a.error.severity) {
526
- return -1;
527
- }
528
- return 0;
529
- };
530
- const ErrorReporting = ({ detectedErrors }) => {
531
- const errors = Array.from(detectedErrors.entries()).flatMap(([clusterName, resourceErrors]) => {
532
- return resourceErrors.map((e) => ({
533
- clusterName,
534
- error: e
535
- }));
536
- }).sort(sortBySeverity);
537
- return /* @__PURE__ */ React.createElement(React.Fragment, null, errors.length !== 0 && /* @__PURE__ */ React.createElement(
538
- Table,
539
- {
540
- title: "Error Reporting",
541
- data: errors,
542
- columns,
543
- options: { paging: true, search: false, emptyRowsWhenPaging: false }
544
- }
545
- ));
546
- };
547
-
548
- const groupResponses = (fetchResponse) => {
549
- return fetchResponse.reduce(
550
- (prev, next) => {
551
- switch (next.type) {
552
- case "deployments":
553
- prev.deployments.push(...next.resources);
554
- break;
555
- case "pods":
556
- prev.pods.push(...next.resources);
557
- break;
558
- case "replicasets":
559
- prev.replicaSets.push(...next.resources);
560
- break;
561
- case "services":
562
- prev.services.push(...next.resources);
563
- break;
564
- case "configmaps":
565
- prev.configMaps.push(...next.resources);
566
- break;
567
- case "horizontalpodautoscalers":
568
- prev.horizontalPodAutoscalers.push(...next.resources);
569
- break;
570
- case "ingresses":
571
- prev.ingresses.push(...next.resources);
572
- break;
573
- case "jobs":
574
- prev.jobs.push(...next.resources);
575
- break;
576
- case "cronjobs":
577
- prev.cronJobs.push(...next.resources);
578
- break;
579
- case "customresources":
580
- prev.customResources.push(...next.resources);
581
- break;
582
- case "statefulsets":
583
- prev.statefulsets.push(...next.resources);
584
- break;
585
- }
586
- return prev;
587
- },
588
- {
589
- pods: [],
590
- replicaSets: [],
591
- deployments: [],
592
- services: [],
593
- configMaps: [],
594
- horizontalPodAutoscalers: [],
595
- ingresses: [],
596
- jobs: [],
597
- cronJobs: [],
598
- customResources: [],
599
- statefulsets: []
600
- }
601
- );
602
- };
603
-
604
- const detectErrorsInObjects = (objects, errorMappers) => {
605
- return objects.flatMap((o) => {
606
- return errorMappers.flatMap((em) => em.detectErrors(o));
607
- });
608
- };
609
-
610
- function isPodReadinessProbeUnready({
611
- container,
612
- containerStatus
613
- }) {
614
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
615
- if (containerStatus.ready || ((_b = (_a = containerStatus.state) == null ? void 0 : _a.running) == null ? void 0 : _b.startedAt) === void 0 || !container.readinessProbe) {
616
- return false;
617
- }
618
- const startDateTime = DateTime.fromISO(
619
- (_d = (_c = containerStatus.state) == null ? void 0 : _c.running) == null ? void 0 : _d.startedAt
620
- ).plus({
621
- seconds: (_f = (_e = container.readinessProbe) == null ? void 0 : _e.initialDelaySeconds) != null ? _f : 0
622
- }).plus({
623
- seconds: ((_h = (_g = container.readinessProbe) == null ? void 0 : _g.periodSeconds) != null ? _h : 0) * ((_j = (_i = container.readinessProbe) == null ? void 0 : _i.failureThreshold) != null ? _j : 0)
624
- });
625
- return startDateTime < DateTime.now();
626
- }
627
- const podToContainerSpecsAndStatuses = (pod) => {
628
- var _a, _b, _c, _d;
629
- const specs = lodash.groupBy((_b = (_a = pod.spec) == null ? void 0 : _a.containers) != null ? _b : [], (value) => value.name);
630
- const result = [];
631
- for (const cs of (_d = (_c = pod.status) == null ? void 0 : _c.containerStatuses) != null ? _d : []) {
632
- const spec = specs[cs.name];
633
- if (spec.length > 0) {
634
- result.push({
635
- container: spec[0],
636
- containerStatus: cs
637
- });
638
- }
639
- }
640
- return result;
641
- };
642
- const readinessProbeProposedFixes = (pod) => {
643
- var _a, _b, _c, _d;
644
- const firstUnreadyContainerStatus = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) == null ? void 0 : _b.find(
645
- (cs) => {
646
- return cs.ready === false;
647
- }
648
- );
649
- return {
650
- errorType: "ReadinessProbeFailed",
651
- rootCauseExplanation: `The container ${firstUnreadyContainerStatus == null ? void 0 : firstUnreadyContainerStatus.name} failed to start properly, but is not crashing`,
652
- actions: [
653
- "Ensure that the container starts correctly locally",
654
- "Check the container's logs looking for error during startup"
655
- ],
656
- type: "events",
657
- podName: (_d = (_c = pod.metadata) == null ? void 0 : _c.name) != null ? _d : ""
658
- };
659
- };
660
- const restartingPodProposedFixes = (pod) => {
661
- var _a, _b, _c;
662
- const lastTerminatedCs = ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).find(
663
- (cs) => {
664
- var _a2;
665
- return ((_a2 = cs.lastState) == null ? void 0 : _a2.terminated) !== void 0;
666
- }
667
- );
668
- const lastTerminated = (_c = lastTerminatedCs == null ? void 0 : lastTerminatedCs.lastState) == null ? void 0 : _c.terminated;
669
- if (!lastTerminated) {
670
- return void 0;
671
- }
672
- switch (lastTerminated == null ? void 0 : lastTerminated.reason) {
673
- case "Unknown":
674
- return {
675
- // TODO check this one, it's more likely a cluster issue
676
- errorType: "Unknown",
677
- rootCauseExplanation: `This container has exited with a non-zero exit code (${lastTerminated.exitCode})`,
678
- actions: ["Check the crash logs for stacktraces"],
679
- container: lastTerminatedCs.name,
680
- type: "logs"
681
- };
682
- case "Error":
683
- return {
684
- errorType: "Error",
685
- rootCauseExplanation: `This container has exited with a non-zero exit code (${lastTerminated.exitCode})`,
686
- actions: ["Check the crash logs for stacktraces"],
687
- container: lastTerminatedCs.name,
688
- type: "logs"
689
- };
690
- case "OOMKilled":
691
- return {
692
- errorType: "OOMKilled",
693
- rootCauseExplanation: `The container "${lastTerminatedCs.name}" has crashed because it has tried to use more memory that it has been allocated`,
694
- actions: [
695
- `Increase the amount of memory assigned to the container`,
696
- "Ensure the application is memory bounded and is not trying to consume too much memory"
697
- ],
698
- docsLink: "https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/#exceed-a-container-s-memory-limit",
699
- type: "docs"
700
- };
701
- default:
702
- return void 0;
703
- }
704
- };
705
- const waitingProposedFix = (pod) => {
706
- var _a, _b, _c, _d, _e;
707
- const waitingCs = ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).find(
708
- (cs) => {
709
- var _a2;
710
- return ((_a2 = cs.state) == null ? void 0 : _a2.waiting) !== void 0;
711
- }
712
- );
713
- const waiting = ((_d = (_c = pod.status) == null ? void 0 : _c.containerStatuses) != null ? _d : []).map((cs) => {
714
- var _a2;
715
- return (_a2 = cs.state) == null ? void 0 : _a2.waiting;
716
- }).find((w) => (w == null ? void 0 : w.reason) !== void 0);
717
- switch (waiting == null ? void 0 : waiting.reason) {
718
- case "InvalidImageName":
719
- return {
720
- errorType: "InvalidImageName",
721
- rootCauseExplanation: "The image in the pod is invalid",
722
- actions: ["Ensure the image name is correct and valid image name"],
723
- type: "docs",
724
- docsLink: "https://docs.docker.com/engine/reference/commandline/tag/#extended-description"
725
- };
726
- case "ImagePullBackOff":
727
- return {
728
- errorType: "ImagePullBackOff",
729
- rootCauseExplanation: "The image either could not be found or Kubernetes does not have permission to pull it",
730
- actions: [
731
- "Ensure the image name is correct",
732
- "Ensure Kubernetes has permission to pull this image"
733
- ],
734
- type: "docs",
735
- docsLink: "https://kubernetes.io/docs/concepts/containers/images/#imagepullbackoff"
736
- };
737
- case "CrashLoopBackOff":
738
- return {
739
- errorType: "CrashLoopBackOff",
740
- rootCauseExplanation: `The container ${waitingCs == null ? void 0 : waitingCs.name} has crashed many times, it will be exponentially restarted until it stops crashing`,
741
- actions: ["Check the crash logs for stacktraces"],
742
- type: "logs",
743
- container: (_e = waitingCs == null ? void 0 : waitingCs.name) != null ? _e : "unknown"
744
- };
745
- case "CreateContainerConfigError":
746
- return {
747
- errorType: "CreateContainerConfigError",
748
- rootCauseExplanation: "There is missing or mismatching configuration required to start the container",
749
- actions: [
750
- "Ensure ConfigMaps references in the Deployment manifest are correct and the keys exist",
751
- "Ensure Secrets references in the Deployment manifest are correct and the keys exist"
752
- ],
753
- type: "docs",
754
- docsLink: "https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/"
755
- };
756
- default:
757
- return void 0;
758
- }
759
- };
760
- const podErrorMappers = [
761
- {
762
- detectErrors: (pod) => {
763
- return podToContainerSpecsAndStatuses(pod).filter(isPodReadinessProbeUnready).map((cs) => {
764
- var _a, _b, _c, _d;
765
- return {
766
- type: "readiness-probe-taking-too-long",
767
- message: `The container ${cs.container.name} failed to start properly, but is not crashing`,
768
- severity: 4,
769
- proposedFix: readinessProbeProposedFixes(pod),
770
- sourceRef: {
771
- name: (_b = (_a = pod.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown pod",
772
- namespace: (_d = (_c = pod.metadata) == null ? void 0 : _c.namespace) != null ? _d : "unknown namespace",
773
- kind: "Pod",
774
- apiGroup: "v1"
775
- },
776
- occurrenceCount: 1
777
- };
778
- });
779
- }
780
- },
781
- {
782
- detectErrors: (pod) => {
783
- var _a, _b;
784
- return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).filter((cs) => {
785
- var _a2, _b2;
786
- return ((_b2 = (_a2 = cs.state) == null ? void 0 : _a2.waiting) == null ? void 0 : _b2.message) !== void 0;
787
- }).map((cs) => {
788
- var _a2, _b2, _c, _d, _e, _f, _g;
789
- return {
790
- type: "container-waiting",
791
- message: (_c = (_b2 = (_a2 = cs.state) == null ? void 0 : _a2.waiting) == null ? void 0 : _b2.message) != null ? _c : "container waiting",
792
- severity: 4,
793
- proposedFix: waitingProposedFix(pod),
794
- sourceRef: {
795
- name: (_e = (_d = pod.metadata) == null ? void 0 : _d.name) != null ? _e : "unknown pod",
796
- namespace: (_g = (_f = pod.metadata) == null ? void 0 : _f.namespace) != null ? _g : "unknown namespace",
797
- kind: "Pod",
798
- apiGroup: "v1"
799
- },
800
- occurrenceCount: 1
801
- };
802
- });
803
- }
804
- },
805
- {
806
- detectErrors: (pod) => {
807
- var _a, _b;
808
- return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).filter((cs) => cs.restartCount > 0).map((cs) => {
809
- var _a2, _b2, _c, _d;
810
- return {
811
- type: "containers-restarting",
812
- message: `container=${cs.name} restarted ${cs.restartCount} times`,
813
- severity: 4,
814
- proposedFix: restartingPodProposedFixes(pod),
815
- sourceRef: {
816
- name: (_b2 = (_a2 = pod.metadata) == null ? void 0 : _a2.name) != null ? _b2 : "unknown pod",
817
- namespace: (_d = (_c = pod.metadata) == null ? void 0 : _c.namespace) != null ? _d : "unknown namespace",
818
- kind: "Pod",
819
- apiGroup: "v1"
820
- },
821
- occurrenceCount: cs.restartCount
822
- };
823
- });
824
- }
825
- }
826
- ];
827
- const detectErrorsInPods = (pods) => detectErrorsInObjects(pods, podErrorMappers);
828
-
829
- const deploymentErrorMappers = [
830
- {
831
- detectErrors: (deployment) => {
832
- var _a, _b;
833
- return ((_b = (_a = deployment.status) == null ? void 0 : _a.conditions) != null ? _b : []).filter((c) => c.status === "False").filter((c) => c.message !== void 0).map((c) => {
834
- var _a2, _b2, _c, _d, _e;
835
- return {
836
- type: "condition-message-present",
837
- message: (_a2 = c.message) != null ? _a2 : "",
838
- severity: 6,
839
- sourceRef: {
840
- name: (_c = (_b2 = deployment.metadata) == null ? void 0 : _b2.name) != null ? _c : "unknown hpa",
841
- namespace: (_e = (_d = deployment.metadata) == null ? void 0 : _d.namespace) != null ? _e : "unknown namespace",
842
- kind: "Deployment",
843
- apiGroup: "apps/v1"
844
- },
845
- occurrenceCount: 1
846
- };
847
- });
848
- }
849
- }
850
- ];
851
- const detectErrorsInDeployments = (deployments) => detectErrorsInObjects(deployments, deploymentErrorMappers);
852
-
853
- const hpaErrorMappers = [
854
- {
855
- detectErrors: (hpa) => {
856
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
857
- if (((_b = (_a = hpa.spec) == null ? void 0 : _a.maxReplicas) != null ? _b : -1) === ((_c = hpa.status) == null ? void 0 : _c.currentReplicas)) {
858
- return [
859
- {
860
- type: "hpa-max-current-replicas",
861
- message: `Current number of replicas (${(_d = hpa.status) == null ? void 0 : _d.currentReplicas}) is equal to the configured max number of replicas (${(_f = (_e = hpa.spec) == null ? void 0 : _e.maxReplicas) != null ? _f : -1})`,
862
- severity: 8,
863
- sourceRef: {
864
- name: (_h = (_g = hpa.metadata) == null ? void 0 : _g.name) != null ? _h : "unknown hpa",
865
- namespace: (_j = (_i = hpa.metadata) == null ? void 0 : _i.namespace) != null ? _j : "unknown namespace",
866
- kind: "HorizontalPodAutoscaler",
867
- apiGroup: "autoscaling/v1"
868
- },
869
- occurrenceCount: 1
870
- }
871
- ];
872
- }
873
- return [];
874
- }
875
- }
876
- ];
877
- const detectErrorsInHpa = (hpas) => detectErrorsInObjects(hpas, hpaErrorMappers);
878
-
879
- const detectErrors = (objects) => {
880
- const errors = /* @__PURE__ */ new Map();
881
- for (const clusterResponse of objects.items) {
882
- let clusterErrors = [];
883
- const groupedResponses = groupResponses(clusterResponse.resources);
884
- clusterErrors = clusterErrors.concat(
885
- detectErrorsInPods(groupedResponses.pods)
886
- );
887
- clusterErrors = clusterErrors.concat(
888
- detectErrorsInDeployments(groupedResponses.deployments)
889
- );
890
- clusterErrors = clusterErrors.concat(
891
- detectErrorsInHpa(
892
- groupedResponses.horizontalPodAutoscalers
893
- )
894
- );
895
- errors.set(clusterResponse.cluster.name, clusterErrors);
896
- }
897
- return errors;
898
- };
899
-
900
- const currentToDeclaredResourceToPerc$1 = (current, resource) => {
901
- if (Number(resource) === 0)
902
- return 0;
903
- if (typeof current === "number" && typeof resource === "number") {
904
- return Math.round(current / resource * 100);
905
- }
906
- const numerator = BigInt(current);
907
- const denominator = BigInt(resource);
908
- return Number(numerator * BigInt(100) / denominator);
909
- };
910
- const bytesToMiB = (value) => {
911
- return `${(parseFloat(value.toString()) / 1024 / 1024).toFixed(0)}MiB`;
912
- };
913
- const formatMillicores = (value) => {
914
- return `${(parseFloat(value.toString()) * 1e3).toFixed(0)}m`;
915
- };
916
-
917
- const useIsPodExecTerminalSupported = () => {
918
- const kubernetesApi = useApi(kubernetesApiRef);
919
- return useAsync(async () => {
920
- const clusters = await kubernetesApi.getClusters();
921
- if (clusters.length !== 1) {
922
- return false;
923
- }
924
- const { authProvider } = clusters[0];
925
- const isClientAuthProvider = ["aks", "google", "oidc"].some(
926
- (authProviderName) => authProvider.includes(authProviderName)
927
- );
928
- return !isClientAuthProvider;
929
- });
930
- };
931
-
932
- const generateAuth = async (entity, kubernetesApi, kubernetesAuthProvidersApi) => {
82
+ const KubernetesContent = ({
83
+ entity,
84
+ refreshIntervalMs
85
+ }) => {
933
86
  var _a;
934
- const clusters = await kubernetesApi.getClusters();
935
- const authProviders = [
936
- ...new Set(
937
- clusters.map(
938
- (c) => `${c.authProvider}${c.oidcTokenProvider ? `.${c.oidcTokenProvider}` : ""}`
939
- )
940
- )
941
- ];
942
- let requestBody = {
943
- entity
944
- };
945
- for (const authProviderStr of authProviders) {
946
- requestBody = await kubernetesAuthProvidersApi.decorateRequestBodyForAuth(
947
- authProviderStr,
948
- requestBody
949
- );
950
- }
951
- return (_a = requestBody.auth) != null ? _a : {};
952
- };
953
-
954
- const useKubernetesObjects = (entity, intervalMs = 1e4) => {
955
- const kubernetesApi = useApi(kubernetesApiRef);
956
- const kubernetesAuthProvidersApi = useApi(kubernetesAuthProvidersApiRef);
957
- const getObjects = useCallback(async () => {
958
- const auth = await generateAuth(
959
- entity,
960
- kubernetesApi,
961
- kubernetesAuthProvidersApi
962
- );
963
- return await kubernetesApi.getObjectsByEntity({
964
- auth,
965
- entity
966
- });
967
- }, [kubernetesApi, entity, kubernetesAuthProvidersApi]);
968
- const { value, loading, error, retry } = useAsyncRetry(
969
- () => getObjects(),
970
- [getObjects]
971
- );
972
- useInterval(() => retry(), intervalMs);
973
- return {
974
- kubernetesObjects: value,
975
- loading,
976
- error: error == null ? void 0 : error.message
977
- };
978
- };
979
-
980
- const useCustomResources = (entity, customResourceMatchers, intervalMs = 1e4) => {
981
- const kubernetesApi = useApi(kubernetesApiRef);
982
- const kubernetesAuthProvidersApi = useApi(kubernetesAuthProvidersApiRef);
983
- const matchersString = JSON.stringify(customResourceMatchers);
984
- const getCustomObjects = useCallback(
985
- async () => {
986
- const auth = await generateAuth(
987
- entity,
988
- kubernetesApi,
989
- kubernetesAuthProvidersApi
990
- );
991
- return await kubernetesApi.getCustomObjectsByEntity({
992
- auth,
993
- customResources: customResourceMatchers,
994
- entity
995
- });
996
- },
997
- // eslint-disable-next-line react-hooks/exhaustive-deps
998
- [kubernetesApi, entity, kubernetesAuthProvidersApi, matchersString]
999
- );
1000
- const { value, loading, error, retry } = useAsyncRetry(
1001
- () => getCustomObjects(),
1002
- [getCustomObjects]
1003
- );
1004
- useInterval(() => retry(), intervalMs);
1005
- return {
1006
- kubernetesObjects: value,
1007
- loading,
1008
- error: error == null ? void 0 : error.message
1009
- };
1010
- };
1011
-
1012
- const PodNamesWithErrorsContext = React__default.createContext(
1013
- /* @__PURE__ */ new Set()
1014
- );
1015
-
1016
- const PodNamesWithMetricsContext = React__default.createContext(/* @__PURE__ */ new Map());
1017
-
1018
- const GroupedResponsesContext = React__default.createContext({
1019
- pods: [],
1020
- replicaSets: [],
1021
- deployments: [],
1022
- services: [],
1023
- configMaps: [],
1024
- horizontalPodAutoscalers: [],
1025
- ingresses: [],
1026
- jobs: [],
1027
- cronJobs: [],
1028
- customResources: [],
1029
- statefulsets: []
1030
- });
1031
-
1032
- const ClusterContext = React__default.createContext({
1033
- name: ""
1034
- });
1035
-
1036
- const PodMetricsContext = React__default.createContext(/* @__PURE__ */ new Map());
1037
- const usePodMetrics = (clusterName, matcher) => {
1038
- var _a, _b, _c, _d;
1039
- const targetRef = {
1040
- name: (_b = (_a = matcher.metadata) == null ? void 0 : _a.name) != null ? _b : "",
1041
- namespace: (_d = (_c = matcher.metadata) == null ? void 0 : _c.namespace) != null ? _d : ""
1042
- };
1043
- const metricsMap = useContext(PodMetricsContext);
1044
- const metrics = metricsMap.get(clusterName);
1045
- return metrics == null ? void 0 : metrics.find((m) => {
1046
- var _a2, _b2, _c2, _d2;
1047
- const pod = m.pod;
1048
- return targetRef.name === ((_b2 = (_a2 = pod.metadata) == null ? void 0 : _a2.name) != null ? _b2 : "") && targetRef.namespace === ((_d2 = (_c2 = pod.metadata) == null ? void 0 : _c2.namespace) != null ? _d2 : "");
1049
- });
1050
- };
1051
-
1052
- const DetectedErrorsContext = React__default.createContext([]);
1053
- const useMatchingErrors = (matcher) => {
1054
- var _a, _b, _c, _d;
1055
- const targetRef = {
1056
- name: (_b = (_a = matcher.metadata) == null ? void 0 : _a.name) != null ? _b : "",
1057
- namespace: (_d = (_c = matcher.metadata) == null ? void 0 : _c.namespace) != null ? _d : "",
1058
- kind: matcher.kind,
1059
- apiGroup: matcher.apiVersion
1060
- };
1061
- const errors = useContext(DetectedErrorsContext);
1062
- return errors.filter((e) => {
1063
- const r = e.sourceRef;
1064
- return targetRef.apiGroup === r.apiGroup && targetRef.kind === r.kind && targetRef.name === r.name && targetRef.namespace === r.namespace;
1065
- });
1066
- };
1067
-
1068
- var __accessCheck = (obj, member, msg) => {
1069
- if (!member.has(obj))
1070
- throw TypeError("Cannot " + msg);
1071
- };
1072
- var __privateGet = (obj, member, getter) => {
1073
- __accessCheck(obj, member, "read from private field");
1074
- return getter ? getter.call(obj) : member.get(obj);
1075
- };
1076
- var __privateAdd = (obj, member, value) => {
1077
- if (member.has(obj))
1078
- throw TypeError("Cannot add the same private member more than once");
1079
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1080
- };
1081
- var _textEncoder;
1082
- class PodExecTerminalAttachAddon extends AttachAddon {
1083
- constructor(socket, options) {
1084
- super(socket, options);
1085
- __privateAdd(this, _textEncoder, new TextEncoder());
1086
- const thisAddon = this;
1087
- thisAddon._sendBinary = (data) => {
1088
- if (!thisAddon._checkOpenSocket()) {
1089
- return;
1090
- }
1091
- const buffer = Uint8Array.from([0, ...__privateGet(this, _textEncoder).encode(data)]);
1092
- thisAddon._socket.send(buffer);
1093
- };
1094
- thisAddon._sendData = (data) => {
1095
- if (!thisAddon._checkOpenSocket()) {
1096
- return;
1097
- }
1098
- thisAddon._sendBinary(data);
1099
- };
1100
- }
1101
- }
1102
- _textEncoder = new WeakMap();
1103
-
1104
- const hasSocketProtocol = (url) => /wss?:\/\//.test(url.toString());
1105
- const PodExecTerminal = (props) => {
1106
- const { containerName, podNamespace, podName } = props;
1107
- const [baseUrl, setBaseUrl] = useState(window.location.host);
1108
- const terminalRef = React__default.useRef(null);
1109
- const discoveryApi = useApi(discoveryApiRef);
1110
- const namespace = podNamespace != null ? podNamespace : "default";
1111
- useEffect(() => {
1112
- discoveryApi.getBaseUrl("kubernetes").then((url) => url != null ? url : window.location.host).then((url) => url.replace(/^http(s?):\/\//, "ws$1://")).then((url) => setBaseUrl(url));
1113
- }, [discoveryApi]);
1114
- const urlParams = useMemo(() => {
1115
- const params = new URLSearchParams({
1116
- container: containerName,
1117
- stdin: "true",
1118
- stdout: "true",
1119
- stderr: "true",
1120
- tty: "true",
1121
- command: "/bin/sh"
1122
- });
1123
- return params;
1124
- }, [containerName]);
1125
- const socketUrl = useMemo(() => {
1126
- if (!hasSocketProtocol(baseUrl)) {
1127
- return "";
1128
- }
1129
- return new URL(
1130
- `${baseUrl}/proxy/api/v1/namespaces/${namespace}/pods/${podName}/exec?${urlParams}`
1131
- );
1132
- }, [baseUrl, namespace, podName, urlParams]);
1133
- useEffect(() => {
1134
- if (!hasSocketProtocol(socketUrl)) {
1135
- return () => {
1136
- };
1137
- }
1138
- const terminal = new Terminal();
1139
- const fitAddon = new FitAddon();
1140
- terminal.loadAddon(fitAddon);
1141
- if (terminalRef.current) {
1142
- terminal.open(terminalRef.current);
1143
- fitAddon.fit();
1144
- }
1145
- terminal.writeln("Starting terminal, please wait...");
1146
- const socket = new WebSocket(socketUrl, ["channel.k8s.io"]);
1147
- socket.onopen = () => {
1148
- terminal.clear();
1149
- const attachAddon = new PodExecTerminalAttachAddon(socket, {
1150
- bidirectional: true
1151
- });
1152
- terminal.loadAddon(attachAddon);
1153
- };
1154
- socket.onclose = () => {
1155
- terminal.writeln("Socket connection closed");
1156
- };
1157
- return () => {
1158
- terminal == null ? void 0 : terminal.clear();
1159
- socket == null ? void 0 : socket.close();
1160
- };
1161
- }, [baseUrl, socketUrl]);
1162
- return /* @__PURE__ */ React__default.createElement(
1163
- "div",
1164
- {
1165
- "data-testid": "terminal",
1166
- ref: terminalRef,
1167
- style: {
1168
- width: "100%",
1169
- height: "100%"
1170
- }
1171
- }
87
+ const { kubernetesObjects, error } = useKubernetesObjects(
88
+ entity,
89
+ refreshIntervalMs
1172
90
  );
1173
- };
1174
-
1175
- const useStyles$3 = makeStyles(
1176
- (theme) => createStyles({
1177
- dialogPaper: { minHeight: "calc(100% - 64px)" },
1178
- dialogContent: { flexBasis: 0 },
1179
- closeButton: {
1180
- position: "absolute",
1181
- right: theme.spacing(1),
1182
- top: theme.spacing(1),
1183
- color: theme.palette.grey[500]
1184
- }
1185
- })
1186
- );
1187
- const PodExecTerminalDialog = (props) => {
1188
- const classes = useStyles$3();
1189
- const { clusterName, containerName, podName } = props;
1190
- const [open, setOpen] = useState(false);
1191
- const isPodExecTerminalSupported = useIsPodExecTerminalSupported();
1192
- const openDialog = () => {
1193
- setOpen(true);
1194
- };
1195
- const closeDialog = () => {
1196
- setOpen(false);
1197
- };
1198
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, !isPodExecTerminalSupported.loading && isPodExecTerminalSupported.value && /* @__PURE__ */ React__default.createElement(
1199
- Dialog,
1200
- {
1201
- maxWidth: false,
1202
- fullWidth: true,
1203
- open,
1204
- onClose: closeDialog,
1205
- PaperProps: { className: classes.dialogPaper }
1206
- },
1207
- /* @__PURE__ */ React__default.createElement(DialogTitle, { id: "dialog-title" }, podName, " - ", containerName, " terminal shell on cluster", " ", clusterName, /* @__PURE__ */ React__default.createElement(
1208
- IconButton,
1209
- {
1210
- "aria-label": "close",
1211
- className: classes.closeButton,
1212
- onClick: closeDialog
1213
- },
1214
- /* @__PURE__ */ React__default.createElement(CloseIcon, null)
1215
- )),
1216
- /* @__PURE__ */ React__default.createElement(DialogContent, { className: classes.dialogContent }, /* @__PURE__ */ React__default.createElement(PodExecTerminal, { ...props }))
1217
- ), /* @__PURE__ */ React__default.createElement(
1218
- Button,
1219
- {
1220
- variant: "outlined",
1221
- "aria-label": "open terminal",
1222
- component: "label",
1223
- disabled: isPodExecTerminalSupported.loading || !isPodExecTerminalSupported.value,
1224
- onClick: openDialog,
1225
- startIcon: /* @__PURE__ */ React__default.createElement(OpenInBrowserIcon, null)
1226
- },
1227
- "Terminal"
1228
- ));
1229
- };
1230
-
1231
- const getProgressColor = ({
1232
- palette,
1233
- value,
1234
- inverse,
1235
- max
1236
- }) => {
1237
- if (isNaN(value)) {
1238
- return palette.status.pending;
1239
- }
1240
- const actualMax = max ? max : 100;
1241
- const actualValue = inverse ? actualMax - value : value;
1242
- if (actualValue >= actualMax) {
1243
- return palette.status.error;
1244
- } else if (actualValue > 90 || actualValue < 40) {
1245
- return palette.status.warning;
1246
- }
1247
- return palette.status.ok;
1248
- };
1249
- const ResourceUtilization = ({
1250
- compressed = false,
1251
- title,
1252
- usage,
1253
- total,
1254
- totalFormatted
1255
- }) => {
1256
- const utilization = currentToDeclaredResourceToPerc$1(usage, total);
1257
- return /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 0 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(
1258
- Typography,
1259
- {
1260
- variant: compressed ? "caption" : "subtitle2"
1261
- },
1262
- `${title}: ${totalFormatted}`
1263
- )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(
1264
- LinearGauge,
91
+ const clustersWithErrors = (_a = kubernetesObjects == null ? void 0 : kubernetesObjects.items.filter((r) => r.errors.length > 0)) != null ? _a : [];
92
+ const detectedErrors = kubernetesObjects !== void 0 ? detectErrors(kubernetesObjects) : /* @__PURE__ */ new Map();
93
+ return /* @__PURE__ */ React.createElement(DetectedErrorsContext.Provider, { value: [...detectedErrors.values()].flat() }, /* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React.createElement(Content, null, kubernetesObjects === void 0 && error === void 0 && /* @__PURE__ */ React.createElement(Progress, null), clustersWithErrors.length > 0 && /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(
94
+ ErrorPanel,
1265
95
  {
1266
- getColor: getProgressColor,
1267
- width: compressed ? "thin" : "thick",
1268
- value: utilization / 100
96
+ entityName: entity.metadata.name,
97
+ clustersWithErrors
1269
98
  }
1270
- ), !compressed && /* @__PURE__ */ React__default.createElement(Typography, { variant: "caption" }, "usage: ", `${utilization}%`)));
1271
- };
1272
-
1273
- const usePodLogs = ({ containerScope, previous }) => {
1274
- const kubernetesProxyApi = useApi(kubernetesProxyApiRef);
1275
- return useAsync(async () => {
1276
- return await kubernetesProxyApi.getPodLogs({
1277
- podName: containerScope.podName,
1278
- namespace: containerScope.podNamespace,
1279
- containerName: containerScope.containerName,
1280
- clusterName: containerScope.clusterName,
1281
- previous
1282
- });
1283
- }, [JSON.stringify(containerScope)]);
1284
- };
1285
-
1286
- const PodLogs = ({
1287
- containerScope,
1288
- previous
1289
- }) => {
1290
- const { value, error, loading } = usePodLogs({
1291
- containerScope,
1292
- previous
1293
- });
1294
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, error && /* @__PURE__ */ React__default.createElement(
1295
- DismissableBanner,
99
+ ))), error !== void 0 && /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(
100
+ ErrorPanel,
1296
101
  {
1297
- ...{
1298
- message: error.message,
1299
- variant: "error",
1300
- fixed: false
1301
- },
1302
- id: "pod-logs"
102
+ entityName: entity.metadata.name,
103
+ errorMessage: error
1303
104
  }
1304
- ), /* @__PURE__ */ React__default.createElement(
1305
- Paper,
105
+ ))), kubernetesObjects && /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(ErrorReporting, { detectedErrors })), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h3" }, "Your Clusters")), /* @__PURE__ */ React.createElement(Grid, { item: true, container: true }, (kubernetesObjects == null ? void 0 : kubernetesObjects.items.length) <= 0 && /* @__PURE__ */ React.createElement(
106
+ Grid,
1306
107
  {
1307
- elevation: 1,
1308
- style: { height: "100%", width: "100%", minHeight: "55rem" }
108
+ container: true,
109
+ justifyContent: "space-around",
110
+ direction: "row",
111
+ alignItems: "center",
112
+ spacing: 2
1309
113
  },
1310
- loading && /* @__PURE__ */ React__default.createElement(Skeleton, { variant: "rect", width: "100%", height: "100%" }),
1311
- !loading && value !== void 0 && (value.text === "" ? /* @__PURE__ */ React__default.createElement(
114
+ /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 8 }, /* @__PURE__ */ React.createElement(
1312
115
  EmptyState,
1313
116
  {
1314
117
  missing: "data",
1315
- title: "No logs emitted",
1316
- description: "No logs were emitted by the container"
1317
- }
1318
- ) : /* @__PURE__ */ React__default.createElement(LogViewer, { text: value.text }))
1319
- ));
1320
- };
1321
-
1322
- const useStyles$2 = makeStyles(
1323
- (theme) => createStyles({
1324
- closeButton: {
1325
- position: "absolute",
1326
- right: theme.spacing(1),
1327
- top: theme.spacing(1),
1328
- color: theme.palette.grey[500]
1329
- }
1330
- })
1331
- );
1332
- const PodLogsDialog = ({ containerScope }) => {
1333
- const classes = useStyles$2();
1334
- const [open, setOpen] = useState(false);
1335
- const openDialog = () => {
1336
- setOpen(true);
1337
- };
1338
- const closeDialog = () => {
1339
- setOpen(false);
1340
- };
1341
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Dialog, { maxWidth: "xl", fullWidth: true, open, onClose: closeDialog }, /* @__PURE__ */ React__default.createElement(DialogTitle, { id: "dialog-title" }, containerScope.podName, " - ", containerScope.containerName, " logs on cluster ", containerScope.clusterName, /* @__PURE__ */ React__default.createElement(
1342
- IconButton,
1343
- {
1344
- "aria-label": "close",
1345
- className: classes.closeButton,
1346
- onClick: closeDialog
1347
- },
1348
- /* @__PURE__ */ React__default.createElement(CloseIcon, null)
1349
- )), /* @__PURE__ */ React__default.createElement(DialogContent, null, /* @__PURE__ */ React__default.createElement(PodLogs, { containerScope }))), /* @__PURE__ */ React__default.createElement(
1350
- Button,
1351
- {
1352
- variant: "outlined",
1353
- "aria-label": "get logs",
1354
- component: "label",
1355
- onClick: openDialog,
1356
- startIcon: /* @__PURE__ */ React__default.createElement(SubjectIcon, null)
1357
- },
1358
- "Logs"
1359
- ));
1360
- };
1361
-
1362
- const getContainerHealthChecks = (containerSpec, containerStatus) => {
1363
- var _a, _b, _c, _d;
1364
- if (((_b = (_a = containerStatus.state) == null ? void 0 : _a.terminated) == null ? void 0 : _b.reason) === "Completed") {
1365
- return {
1366
- "not waiting to start": ((_c = containerStatus.state) == null ? void 0 : _c.waiting) === void 0,
1367
- "no restarts": containerStatus.restartCount === 0
1368
- };
1369
- }
1370
- return {
1371
- "not waiting to start": ((_d = containerStatus.state) == null ? void 0 : _d.waiting) === void 0,
1372
- started: !!containerStatus.started,
1373
- ready: containerStatus.ready,
1374
- "no restarts": containerStatus.restartCount === 0,
1375
- "readiness probe set": containerSpec && (containerSpec == null ? void 0 : containerSpec.readinessProbe) !== void 0
1376
- };
1377
- };
1378
- const getCurrentState = (containerStatus) => {
1379
- var _a, _b, _c, _d, _e;
1380
- return ((_b = (_a = containerStatus.state) == null ? void 0 : _a.waiting) == null ? void 0 : _b.reason) || ((_d = (_c = containerStatus.state) == null ? void 0 : _c.terminated) == null ? void 0 : _d.reason) || (((_e = containerStatus.state) == null ? void 0 : _e.running) !== void 0 ? "Running" : "Unknown");
1381
- };
1382
- const getStartedAtTime = (containerStatus) => {
1383
- var _a, _b, _c, _d;
1384
- return ((_b = (_a = containerStatus.state) == null ? void 0 : _a.running) == null ? void 0 : _b.startedAt) || ((_d = (_c = containerStatus.state) == null ? void 0 : _c.terminated) == null ? void 0 : _d.startedAt);
1385
- };
1386
- const ContainerDatetime = ({ prefix, dateTime }) => {
1387
- return /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, prefix, ":", " ", DateTime.fromISO(dateTime).toRelative({
1388
- locale: "en"
1389
- }));
1390
- };
1391
- const ContainerCard = ({
1392
- podScope,
1393
- containerSpec,
1394
- containerStatus,
1395
- containerMetrics
1396
- }) => {
1397
- var _a, _b;
1398
- if (containerSpec === void 0) {
1399
- return /* @__PURE__ */ React__default.createElement(Typography, null, "error reading pod from cluster");
1400
- }
1401
- const containerStartedTime = getStartedAtTime(containerStatus);
1402
- const containerFinishedTime = (_b = (_a = containerStatus.state) == null ? void 0 : _a.terminated) == null ? void 0 : _b.finishedAt;
1403
- return /* @__PURE__ */ React__default.createElement(Card, null, /* @__PURE__ */ React__default.createElement(
1404
- CardHeader,
1405
- {
1406
- title: containerStatus.name,
1407
- subheader: containerStatus.image
1408
- }
1409
- ), /* @__PURE__ */ React__default.createElement(CardContent, null, /* @__PURE__ */ React__default.createElement(Grid, { container: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, containerStartedTime && /* @__PURE__ */ React__default.createElement(
1410
- ContainerDatetime,
1411
- {
1412
- prefix: "Started",
1413
- dateTime: containerStartedTime
1414
- }
1415
- ), containerFinishedTime && /* @__PURE__ */ React__default.createElement(
1416
- ContainerDatetime,
1417
- {
1418
- prefix: "Completed",
1419
- dateTime: containerFinishedTime
1420
- }
1421
- ), containerStartedTime && containerFinishedTime && /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Execution time:", " ", DateTime.fromISO(containerFinishedTime).diff(DateTime.fromISO(containerStartedTime), [
1422
- "hours",
1423
- "minutes",
1424
- "seconds"
1425
- ]).toHuman())), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Status: ", getCurrentState(containerStatus))), containerStatus.restartCount > 0 && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Restarts: ", containerStatus.restartCount)), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Container health")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(
1426
- StructuredMetadataTable,
1427
- {
1428
- metadata: getContainerHealthChecks(
1429
- containerSpec,
1430
- containerStatus
1431
- )
1432
- }
1433
- )), containerMetrics && /* @__PURE__ */ React__default.createElement(Grid, { container: true, item: true, xs: 12, spacing: 0 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle1" }, "Resource utilization")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12, style: { minHeight: "5rem" } }, /* @__PURE__ */ React__default.createElement(
1434
- ResourceUtilization,
1435
- {
1436
- compressed: true,
1437
- title: "CPU requests",
1438
- usage: containerMetrics.cpuUsage.currentUsage,
1439
- total: containerMetrics.cpuUsage.requestTotal,
1440
- totalFormatted: formatMillicores(
1441
- containerMetrics.cpuUsage.requestTotal
1442
- )
1443
- }
1444
- ), /* @__PURE__ */ React__default.createElement(
1445
- ResourceUtilization,
1446
- {
1447
- compressed: true,
1448
- title: "CPU limits",
1449
- usage: containerMetrics.cpuUsage.currentUsage,
1450
- total: containerMetrics.cpuUsage.limitTotal,
1451
- totalFormatted: formatMillicores(
1452
- containerMetrics.cpuUsage.limitTotal
1453
- )
1454
- }
1455
- ), /* @__PURE__ */ React__default.createElement(
1456
- ResourceUtilization,
1457
- {
1458
- compressed: true,
1459
- title: "Memory requests",
1460
- usage: containerMetrics.memoryUsage.currentUsage,
1461
- total: containerMetrics.memoryUsage.requestTotal,
1462
- totalFormatted: bytesToMiB(
1463
- containerMetrics.memoryUsage.requestTotal
1464
- )
1465
- }
1466
- ), /* @__PURE__ */ React__default.createElement(
1467
- ResourceUtilization,
1468
- {
1469
- compressed: true,
1470
- title: "Memory limits",
1471
- usage: containerMetrics.memoryUsage.currentUsage,
1472
- total: containerMetrics.memoryUsage.limitTotal,
1473
- totalFormatted: bytesToMiB(
1474
- containerMetrics.memoryUsage.limitTotal
1475
- )
1476
- }
1477
- ))))), /* @__PURE__ */ React__default.createElement(CardActions, null, /* @__PURE__ */ React__default.createElement(
1478
- PodLogsDialog,
1479
- {
1480
- containerScope: {
1481
- containerName: containerStatus.name,
1482
- ...podScope
1483
- }
1484
- }
1485
- ), /* @__PURE__ */ React__default.createElement(
1486
- PodExecTerminalDialog,
1487
- {
1488
- clusterName: podScope.clusterName,
1489
- containerName: containerStatus.name,
1490
- podName: podScope.podName,
1491
- podNamespace: podScope.podNamespace
1492
- }
1493
- )));
1494
- };
1495
-
1496
- const kindMappings$3 = {
1497
- deployment: "deployment",
1498
- pod: "pod",
1499
- ingress: "ingress",
1500
- service: "service",
1501
- horizontalpodautoscaler: "deployment",
1502
- statefulset: "statefulset"
1503
- };
1504
- function standardFormatter(options) {
1505
- var _a, _b, _c, _d;
1506
- if (!options.dashboardUrl) {
1507
- throw new Error("standard dashboard requires a dashboardUrl option");
1508
- }
1509
- const result = new URL(options.dashboardUrl.href);
1510
- const name = encodeURIComponent((_b = (_a = options.object.metadata) == null ? void 0 : _a.name) != null ? _b : "");
1511
- const namespace = encodeURIComponent(
1512
- (_d = (_c = options.object.metadata) == null ? void 0 : _c.namespace) != null ? _d : ""
1513
- );
1514
- const validKind = kindMappings$3[options.kind.toLocaleLowerCase("en-US")];
1515
- if (!result.pathname.endsWith("/")) {
1516
- result.pathname += "/";
1517
- }
1518
- if (validKind && name && namespace) {
1519
- result.hash = `/${validKind}/${namespace}/${name}`;
1520
- } else if (namespace) {
1521
- result.hash = "/workloads";
1522
- }
1523
- if (namespace) {
1524
- result.hash += `?namespace=${namespace}`;
1525
- }
1526
- return result;
1527
- }
1528
-
1529
- const kindMappings$2 = {
1530
- deployment: "apps.deployment",
1531
- ingress: "networking.k8s.io.ingress",
1532
- service: "service",
1533
- horizontalpodautoscaler: "autoscaling.horizontalpodautoscaler"
1534
- };
1535
- function rancherFormatter(options) {
1536
- var _a, _b, _c, _d;
1537
- if (!options.dashboardUrl) {
1538
- throw new Error("Rancher dashboard requires a dashboardUrl option");
1539
- }
1540
- const basePath = new URL(options.dashboardUrl.href);
1541
- const name = encodeURIComponent((_b = (_a = options.object.metadata) == null ? void 0 : _a.name) != null ? _b : "");
1542
- const namespace = encodeURIComponent(
1543
- (_d = (_c = options.object.metadata) == null ? void 0 : _c.namespace) != null ? _d : ""
1544
- );
1545
- const validKind = kindMappings$2[options.kind.toLocaleLowerCase("en-US")];
1546
- if (!basePath.pathname.endsWith("/")) {
1547
- basePath.pathname += "/";
1548
- }
1549
- let path = "";
1550
- if (validKind && name && namespace) {
1551
- path = `explorer/${validKind}/${namespace}/${name}`;
1552
- } else if (namespace) {
1553
- path = "explorer/workload";
1554
- }
1555
- return new URL(path, basePath);
1556
- }
1557
-
1558
- const kindMappings$1 = {
1559
- deployment: "deployments",
1560
- ingress: "ingresses",
1561
- service: "services",
1562
- horizontalpodautoscaler: "horizontalpodautoscalers",
1563
- persistentvolume: "persistentvolumes"
1564
- };
1565
- function openshiftFormatter(options) {
1566
- var _a, _b, _c, _d;
1567
- if (!options.dashboardUrl) {
1568
- throw new Error("OpenShift dashboard requires a dashboardUrl option");
1569
- }
1570
- const basePath = new URL(options.dashboardUrl.href);
1571
- const name = encodeURIComponent((_b = (_a = options.object.metadata) == null ? void 0 : _a.name) != null ? _b : "");
1572
- const namespace = encodeURIComponent(
1573
- (_d = (_c = options.object.metadata) == null ? void 0 : _c.namespace) != null ? _d : ""
1574
- );
1575
- const validKind = kindMappings$1[options.kind.toLocaleLowerCase("en-US")];
1576
- if (!basePath.pathname.endsWith("/")) {
1577
- basePath.pathname += "/";
1578
- }
1579
- let path = "";
1580
- if (namespace) {
1581
- if (name && validKind) {
1582
- path = `k8s/ns/${namespace}/${validKind}/${name}`;
1583
- } else {
1584
- path = `k8s/cluster/projects/${namespace}`;
1585
- }
1586
- } else if (validKind) {
1587
- path = `k8s/cluster/${validKind}`;
1588
- if (name) {
1589
- path += `/${name}`;
1590
- }
1591
- }
1592
- return new URL(path, basePath);
1593
- }
1594
-
1595
- const basePath = "https://portal.azure.com/#blade/Microsoft_Azure_ContainerService/AksK8ResourceMenuBlade/overview-Deployment/aksClusterId";
1596
- const requiredParams = ["subscriptionId", "resourceGroup", "clusterName"];
1597
- function aksFormatter(options) {
1598
- if (!options.dashboardParameters) {
1599
- throw new Error("AKS dashboard requires a dashboardParameters option");
1600
- }
1601
- const args = options.dashboardParameters;
1602
- for (const param of requiredParams) {
1603
- if (typeof args[param] !== "string") {
1604
- throw new Error(
1605
- `AKS dashboard requires a "${param}" of type string in the dashboardParameters option`
1606
- );
1607
- }
1608
- }
1609
- const path = `/subscriptions/${args.subscriptionId}/resourceGroups/${args.resourceGroup}/providers/Microsoft.ContainerService/managedClusters/${args.clusterName}`;
1610
- const { name, namespace, uid } = options.object.metadata;
1611
- const { selector } = options.object.spec;
1612
- const params = {
1613
- kind: options.kind,
1614
- metadata: { name, namespace, uid },
1615
- spec: {
1616
- selector
1617
- }
1618
- };
1619
- return new URL(
1620
- `${basePath}/${encodeURIComponent(path)}/resource/${encodeURIComponent(
1621
- JSON.stringify(params)
1622
- )}`
1623
- );
1624
- }
1625
-
1626
- function eksFormatter(_options) {
1627
- throw new Error("EKS formatter is not yet implemented. Please, contribute!");
1628
- }
1629
-
1630
- const kindMappings = {
1631
- deployment: "deployment",
1632
- pod: "pod",
1633
- ingress: "ingress",
1634
- service: "service",
1635
- horizontalpodautoscaler: "deployment"
1636
- };
1637
- function gkeFormatter(options) {
1638
- var _a, _b, _c, _d;
1639
- if (!options.dashboardParameters) {
1640
- throw new Error("GKE dashboard requires a dashboardParameters option");
1641
- }
1642
- const args = options.dashboardParameters;
1643
- if (typeof args.projectId !== "string") {
1644
- throw new Error(
1645
- 'GKE dashboard requires a "projectId" of type string in the dashboardParameters option'
1646
- );
1647
- }
1648
- if (typeof args.region !== "string") {
1649
- throw new Error(
1650
- 'GKE dashboard requires a "region" of type string in the dashboardParameters option'
1651
- );
1652
- }
1653
- if (typeof args.clusterName !== "string") {
1654
- throw new Error(
1655
- 'GKE dashboard requires a "clusterName" of type string in the dashboardParameters option'
1656
- );
1657
- }
1658
- const basePath = new URL("https://console.cloud.google.com/");
1659
- const region = encodeURIComponent(args.region);
1660
- const clusterName = encodeURIComponent(args.clusterName);
1661
- const name = encodeURIComponent((_b = (_a = options.object.metadata) == null ? void 0 : _a.name) != null ? _b : "");
1662
- const namespace = encodeURIComponent(
1663
- (_d = (_c = options.object.metadata) == null ? void 0 : _c.namespace) != null ? _d : ""
1664
- );
1665
- const validKind = kindMappings[options.kind.toLocaleLowerCase("en-US")];
1666
- let path = "";
1667
- if (namespace && name && validKind) {
1668
- const kindsWithDetails = ["ingress", "pod"];
1669
- const landingPage = kindsWithDetails.includes(validKind) ? "details" : "overview";
1670
- path = `kubernetes/${validKind}/${region}/${clusterName}/${namespace}/${name}/${landingPage}`;
1671
- } else {
1672
- path = `kubernetes/clusters/details/${region}/${clusterName}/details`;
1673
- }
1674
- const result = new URL(path, basePath);
1675
- result.searchParams.set("project", args.projectId);
1676
- return result;
1677
- }
1678
-
1679
- const clusterLinksFormatters = {
1680
- standard: standardFormatter,
1681
- rancher: rancherFormatter,
1682
- openshift: openshiftFormatter,
1683
- aks: aksFormatter,
1684
- eks: eksFormatter,
1685
- gke: gkeFormatter
1686
- };
1687
- const defaultFormatterName = "standard";
1688
-
1689
- function formatClusterLink(options) {
1690
- if (!options.dashboardUrl && !options.dashboardParameters) {
1691
- return void 0;
1692
- }
1693
- if (options.dashboardUrl && !options.object) {
1694
- return options.dashboardUrl;
1695
- }
1696
- const app = options.dashboardApp || defaultFormatterName;
1697
- const formatter = clusterLinksFormatters[app];
1698
- if (!formatter) {
1699
- throw new Error(`Could not find Kubernetes dashboard app named '${app}'`);
1700
- }
1701
- const url = formatter({
1702
- dashboardUrl: options.dashboardUrl ? new URL(options.dashboardUrl) : void 0,
1703
- dashboardParameters: options.dashboardParameters,
1704
- object: options.object,
1705
- kind: options.kind
1706
- });
1707
- return url.toString();
1708
- }
1709
-
1710
- const ManifestYaml = ({ object }) => {
1711
- const [managedFields, setManagedFields] = useState(false);
1712
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
1713
- FormControlLabel,
1714
- {
1715
- control: /* @__PURE__ */ React__default.createElement(
1716
- Switch,
1717
- {
1718
- checked: managedFields,
1719
- onChange: (event) => {
1720
- setManagedFields(event.target.checked);
1721
- },
1722
- name: "Managed Fields"
1723
- }
1724
- ),
1725
- label: "Managed Fields"
1726
- }
1727
- ), /* @__PURE__ */ React__default.createElement(
1728
- CodeSnippet,
1729
- {
1730
- language: "yaml",
1731
- text: jsyaml.dump(object, {
1732
- // NOTE: this will remove any field called `managedFields`
1733
- // not just the metadata one
1734
- // TODO: @mclarke make this only remove the `metadata.managedFields`
1735
- replacer: (key, value) => {
1736
- if (!managedFields) {
1737
- return key === "managedFields" ? void 0 : value;
1738
- }
1739
- return value;
1740
- }
1741
- })
1742
- }
1743
- ));
1744
- };
1745
-
1746
- const useDrawerStyles$1 = makeStyles(
1747
- (theme) => createStyles({
1748
- paper: {
1749
- width: "50%",
1750
- justifyContent: "space-between",
1751
- padding: theme.spacing(2.5)
1752
- }
1753
- })
1754
- );
1755
- const useDrawerContentStyles$2 = makeStyles(
1756
- (_) => createStyles({
1757
- header: {
1758
- display: "flex",
1759
- flexDirection: "row",
1760
- justifyContent: "space-between"
1761
- },
1762
- errorMessage: {
1763
- marginTop: "1em",
1764
- marginBottom: "1em"
1765
- },
1766
- options: {
1767
- display: "flex",
1768
- flexDirection: "row",
1769
- justifyContent: "space-between"
1770
- },
1771
- icon: {
1772
- fontSize: 20
1773
- },
1774
- content: {
1775
- height: "80%"
1776
- }
1777
- })
1778
- );
1779
- const PodDrawerButton = withStyles({
1780
- root: {
1781
- padding: "6px 5px"
1782
- },
1783
- label: {
1784
- textTransform: "none"
1785
- }
1786
- })(Button);
1787
- const LinkErrorPanel = ({ cluster, errorMessage }) => /* @__PURE__ */ React__default.createElement(
1788
- WarningPanel,
1789
- {
1790
- title: "There was a problem formatting the link to the Kubernetes dashboard",
1791
- message: `Could not format the link to the dashboard of your cluster named '${cluster.name}'. Its dashboardApp property has been set to '${cluster.dashboardApp || "standard"}.'`
1792
- },
1793
- errorMessage && /* @__PURE__ */ React__default.createElement(Typography, { variant: "body2" }, "Errors: ", errorMessage)
1794
- );
1795
- function replaceNullsWithUndefined(someObj) {
1796
- const replacer = (_, value) => String(value) === "null" || String(value) === "undefined" ? void 0 : value;
1797
- return JSON.parse(JSON.stringify(someObj, replacer));
1798
- }
1799
- function tryFormatClusterLink(options) {
1800
- try {
1801
- return {
1802
- clusterLink: formatClusterLink(options),
1803
- errorMessage: ""
1804
- };
1805
- } catch (err) {
1806
- return {
1807
- clusterLink: "",
1808
- errorMessage: err.message || err.toString()
1809
- };
1810
- }
1811
- }
1812
- const KubernetesStructuredMetadataTableDrawerContent = ({
1813
- toggleDrawer,
1814
- object,
1815
- renderObject,
1816
- kind
1817
- }) => {
1818
- var _a, _b;
1819
- const [isYaml, setIsYaml] = useState(false);
1820
- const classes = useDrawerContentStyles$2();
1821
- const cluster = useContext(ClusterContext);
1822
- const { clusterLink, errorMessage } = tryFormatClusterLink({
1823
- dashboardUrl: cluster.dashboardUrl,
1824
- dashboardApp: cluster.dashboardApp,
1825
- dashboardParameters: cluster.dashboardParameters,
1826
- object,
1827
- kind
1828
- });
1829
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: classes.header }, /* @__PURE__ */ React__default.createElement(Grid, { container: true, justifyContent: "flex-start", alignItems: "flex-start" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, (_b = (_a = object.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown name")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 1 }, /* @__PURE__ */ React__default.createElement(
1830
- IconButton,
1831
- {
1832
- key: "dismiss",
1833
- title: "Close the drawer",
1834
- onClick: (e) => toggleDrawer(e, false),
1835
- color: "inherit"
1836
- },
1837
- /* @__PURE__ */ React__default.createElement(CloseIcon, { className: classes.icon })
1838
- )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "body1" }, kind)), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React__default.createElement(
1839
- FormControlLabel,
1840
- {
1841
- control: /* @__PURE__ */ React__default.createElement(
1842
- Switch,
1843
- {
1844
- checked: isYaml,
1845
- onChange: (event) => {
1846
- setIsYaml(event.target.checked);
1847
- },
1848
- name: "YAML"
1849
- }
1850
- ),
1851
- label: "YAML"
1852
- }
1853
- )))), errorMessage && /* @__PURE__ */ React__default.createElement("div", { className: classes.errorMessage }, /* @__PURE__ */ React__default.createElement(LinkErrorPanel, { cluster, errorMessage })), /* @__PURE__ */ React__default.createElement("div", { className: classes.options }, /* @__PURE__ */ React__default.createElement("div", null, clusterLink && /* @__PURE__ */ React__default.createElement(
1854
- LinkButton,
1855
- {
1856
- variant: "outlined",
1857
- color: "primary",
1858
- size: "small",
1859
- to: clusterLink,
1860
- endIcon: /* @__PURE__ */ React__default.createElement(OpenInNewIcon, null)
1861
- },
1862
- "Open Kubernetes Dashboard"
1863
- ))), /* @__PURE__ */ React__default.createElement("div", { className: classes.content }, isYaml && /* @__PURE__ */ React__default.createElement(ManifestYaml, { object }), !isYaml && /* @__PURE__ */ React__default.createElement(
1864
- StructuredMetadataTable,
1865
- {
1866
- metadata: renderObject(replaceNullsWithUndefined(object))
1867
- }
1868
- )));
1869
- };
1870
- const KubernetesStructuredMetadataTableDrawer = ({
1871
- object,
1872
- renderObject,
1873
- kind,
1874
- buttonVariant = "subtitle2",
1875
- expanded = false,
1876
- children
1877
- }) => {
1878
- var _a, _b;
1879
- const [isOpen, setIsOpen] = useState(expanded);
1880
- const classes = useDrawerStyles$1();
1881
- const toggleDrawer = (e, newValue) => {
1882
- e.stopPropagation();
1883
- setIsOpen(newValue);
1884
- };
1885
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
1886
- PodDrawerButton,
1887
- {
1888
- onClick: (e) => toggleDrawer(e, true),
1889
- onFocus: (event) => event.stopPropagation()
1890
- },
1891
- children === void 0 ? /* @__PURE__ */ React__default.createElement(Typography, { variant: buttonVariant }, (_b = (_a = object.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown object") : children
1892
- ), /* @__PURE__ */ React__default.createElement(
1893
- Drawer,
1894
- {
1895
- classes: {
1896
- paper: classes.paper
1897
- },
1898
- anchor: "right",
1899
- open: isOpen,
1900
- onClose: (e) => toggleDrawer(e, false),
1901
- onClick: (event) => event.stopPropagation()
1902
- },
1903
- /* @__PURE__ */ React__default.createElement(
1904
- KubernetesStructuredMetadataTableDrawerContent,
1905
- {
1906
- kind,
1907
- toggleDrawer,
1908
- object,
1909
- renderObject
1910
- }
1911
- )
1912
- ));
1913
- };
1914
-
1915
- const useDrawerContentStyles$1 = makeStyles(
1916
- (_theme) => createStyles({
1917
- header: {
1918
- display: "flex",
1919
- flexDirection: "row",
1920
- justifyContent: "space-between"
1921
- },
1922
- content: {
1923
- height: "80%"
1924
- },
1925
- icon: {
1926
- fontSize: 20
1927
- }
1928
- })
1929
- );
1930
- const KubernetesDrawerContent = ({
1931
- children,
1932
- header,
1933
- kubernetesObject,
1934
- close
1935
- }) => {
1936
- var _a;
1937
- const classes = useDrawerContentStyles$1();
1938
- const [isYaml, setIsYaml] = useState(false);
1939
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement("div", { className: classes.header }, /* @__PURE__ */ React__default.createElement(Grid, { container: true, justifyContent: "flex-start", alignItems: "flex-start" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, (_a = kubernetesObject.metadata) == null ? void 0 : _a.name)), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 1 }, /* @__PURE__ */ React__default.createElement(
1940
- IconButton,
1941
- {
1942
- key: "dismiss",
1943
- title: "Close the drawer",
1944
- onClick: () => close(),
1945
- color: "inherit"
1946
- },
1947
- /* @__PURE__ */ React__default.createElement(CloseIcon, { className: classes.icon })
1948
- )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, header), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(
1949
- FormControlLabel,
1950
- {
1951
- control: /* @__PURE__ */ React__default.createElement(
1952
- Switch,
1953
- {
1954
- checked: isYaml,
1955
- onChange: (event) => {
1956
- setIsYaml(event.target.checked);
1957
- },
1958
- name: "YAML"
1959
- }
1960
- ),
1961
- label: "YAML"
1962
- }
1963
- )))), /* @__PURE__ */ React__default.createElement("div", { className: classes.content }, isYaml && /* @__PURE__ */ React__default.createElement(ManifestYaml, { object: kubernetesObject }), !isYaml && children));
1964
- };
1965
- const useDrawerStyles = makeStyles(
1966
- (theme) => createStyles({
1967
- paper: {
1968
- width: "50%",
1969
- justifyContent: "space-between",
1970
- padding: theme.spacing(2.5)
1971
- }
1972
- })
1973
- );
1974
- const DrawerButton = withStyles$1({
1975
- root: {
1976
- padding: "6px 5px"
1977
- },
1978
- label: {
1979
- textTransform: "none"
1980
- }
1981
- })(Button);
1982
- const KubernetesDrawer = ({
1983
- open,
1984
- label,
1985
- drawerContentsHeader,
1986
- kubernetesObject,
1987
- children
1988
- }) => {
1989
- const classes = useDrawerStyles();
1990
- const [isOpen, setIsOpen] = useState(open != null ? open : false);
1991
- const toggleDrawer = (e, newValue) => {
1992
- e.stopPropagation();
1993
- setIsOpen(newValue);
1994
- };
1995
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(DrawerButton, { onClick: () => setIsOpen(true) }, label), /* @__PURE__ */ React__default.createElement(
1996
- Drawer,
1997
- {
1998
- classes: {
1999
- paper: classes.paper
2000
- },
2001
- anchor: "right",
2002
- open: isOpen,
2003
- onClose: (e) => toggleDrawer(e, false),
2004
- onClick: (event) => event.stopPropagation()
2005
- },
2006
- isOpen && /* @__PURE__ */ React__default.createElement(
2007
- KubernetesDrawerContent,
2008
- {
2009
- header: drawerContentsHeader,
2010
- kubernetesObject,
2011
- children,
2012
- close: () => setIsOpen(false)
2013
- }
2014
- )
2015
- ));
2016
- };
2017
-
2018
- const PodCondition = ({ condition }) => {
2019
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, condition.status === "False" && /* @__PURE__ */ React__default.createElement(StatusError, null, condition.type, " - (", condition.reason, " ", condition.lastTransitionTime && DateTime.fromISO(condition.lastTransitionTime).toRelative({
2020
- locale: "en"
2021
- }), ") - ", condition.message, " "), condition.status === "True" && /* @__PURE__ */ React__default.createElement(StatusOK, null, condition.type, " - (", condition.lastTransitionTime && DateTime.fromISO(condition.lastTransitionTime).toRelative({
2022
- locale: "en"
2023
- }), ")"), condition.status === "Unknown" && /* @__PURE__ */ React__default.createElement(StatusWarning, null, condition.type, " - (", condition.lastTransitionTime && DateTime.fromISO(condition.lastTransitionTime).toRelative({
2024
- locale: "en"
2025
- }), ") ", condition.message));
2026
- };
2027
- const PendingPodContent = ({ pod }) => {
2028
- var _a, _b, _c, _d, _e, _f, _g, _h;
2029
- const startupConditions = [
2030
- (_b = (_a = pod.status) == null ? void 0 : _a.conditions) == null ? void 0 : _b.find((c) => c.type === "PodScheduled"),
2031
- (_d = (_c = pod.status) == null ? void 0 : _c.conditions) == null ? void 0 : _d.find((c) => c.type === "Initialized"),
2032
- (_f = (_e = pod.status) == null ? void 0 : _e.conditions) == null ? void 0 : _f.find((c) => c.type === "ContainersReady"),
2033
- (_h = (_g = pod.status) == null ? void 0 : _g.conditions) == null ? void 0 : _h.find((c) => c.type === "Ready")
2034
- ].filter((c) => !!c);
2035
- return /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, "Pod is Pending. Conditions:"), /* @__PURE__ */ React__default.createElement(List, null, startupConditions.map((c) => /* @__PURE__ */ React__default.createElement(ListItem, { key: c.type }, /* @__PURE__ */ React__default.createElement(PodCondition, { condition: c }))))));
2036
- };
2037
-
2038
- const useEvents = ({
2039
- involvedObjectName,
2040
- namespace,
2041
- clusterName
2042
- }) => {
2043
- const kubernetesProxyApi = useApi(kubernetesProxyApiRef);
2044
- return useAsync(async () => {
2045
- return await kubernetesProxyApi.getEventsByInvolvedObjectName({
2046
- involvedObjectName,
2047
- namespace,
2048
- clusterName
2049
- });
2050
- }, [involvedObjectName, namespace, clusterName]);
2051
- };
2052
-
2053
- const getAvatarByType = (type) => {
2054
- return /* @__PURE__ */ React__default.createElement(ListItemAvatar, null, /* @__PURE__ */ React__default.createElement(Avatar, null, type === "Warning" ? /* @__PURE__ */ React__default.createElement(WarningIcon, null) : /* @__PURE__ */ React__default.createElement(InfoIcon, null)));
2055
- };
2056
- const EventsContent = ({
2057
- events,
2058
- warningEventsOnly
2059
- }) => {
2060
- if (events.length === 0) {
2061
- return /* @__PURE__ */ React__default.createElement(Typography, null, "No events found");
2062
- }
2063
- return /* @__PURE__ */ React__default.createElement(Container, null, /* @__PURE__ */ React__default.createElement(Grid, null, /* @__PURE__ */ React__default.createElement(List, null, events.filter((event) => {
2064
- if (warningEventsOnly) {
2065
- return event.type === "Warning";
2066
- }
2067
- return true;
2068
- }).map((event) => {
2069
- var _a;
2070
- const timeAgo = event.metadata.creationTimestamp ? DateTime.fromISO(event.metadata.creationTimestamp).toRelative(
2071
- {
2072
- locale: "en"
2073
- }
2074
- ) : "unknown";
2075
- return /* @__PURE__ */ React__default.createElement(ListItem, { key: event.metadata.name }, /* @__PURE__ */ React__default.createElement(Tooltip, { title: `${(_a = event.type) != null ? _a : ""} event` }, getAvatarByType(event.type)), /* @__PURE__ */ React__default.createElement(
2076
- ListItemText,
2077
- {
2078
- primary: `First event ${timeAgo} (count: ${event.count})`,
2079
- secondary: `${event.reason}: ${event.message}`
2080
- }
2081
- ));
2082
- }))));
2083
- };
2084
- const Events = ({
2085
- involvedObjectName,
2086
- namespace,
2087
- clusterName,
2088
- warningEventsOnly
2089
- }) => {
2090
- const { value, error, loading } = useEvents({
2091
- involvedObjectName,
2092
- namespace,
2093
- clusterName
2094
- });
2095
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, error && /* @__PURE__ */ React__default.createElement(
2096
- DismissableBanner,
2097
- {
2098
- ...{
2099
- message: error.message,
2100
- variant: "error",
2101
- fixed: false
2102
- },
2103
- id: "events"
2104
- }
2105
- ), loading && /* @__PURE__ */ React__default.createElement(Skeleton, { variant: "rect", width: "100%", height: "100%" }), !loading && value !== void 0 && /* @__PURE__ */ React__default.createElement(EventsContent, { warningEventsOnly, events: value }));
2106
- };
2107
-
2108
- const useStyles$1 = makeStyles$1(
2109
- (theme) => createStyles$1({
2110
- closeButton: {
2111
- position: "absolute",
2112
- right: theme.spacing(1),
2113
- top: theme.spacing(1),
2114
- color: theme.palette.grey[500]
2115
- }
2116
- })
2117
- );
2118
- const FixDialog = ({
2119
- open,
2120
- pod,
2121
- error,
2122
- clusterName
2123
- }) => {
2124
- var _a;
2125
- const [isOpen, setOpen] = useState(!!open);
2126
- const classes = useStyles$1();
2127
- const openDialog = () => {
2128
- setOpen(true);
2129
- };
2130
- const closeDialog = () => {
2131
- setOpen(false);
2132
- };
2133
- const pf = error.proposedFix;
2134
- const dialogContent = () => {
2135
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
2136
- return /* @__PURE__ */ React__default.createElement(Grid, { container: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography$1, { variant: "h6" }, "Detected error:"), /* @__PURE__ */ React__default.createElement(Typography$1, null, error.message)), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography$1, { variant: "h6" }, "Cause explanation:"), /* @__PURE__ */ React__default.createElement(Typography$1, null, (_b = (_a2 = error.proposedFix) == null ? void 0 : _a2.rootCauseExplanation) != null ? _b : "unknown")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography$1, { variant: "h6" }, "Fix:"), /* @__PURE__ */ React__default.createElement(Typography$1, null, /* @__PURE__ */ React__default.createElement("ul", null, ((_d = (_c = error.proposedFix) == null ? void 0 : _c.actions) != null ? _d : []).map((fix, i) => {
2137
- var _a3, _b2;
2138
- return /* @__PURE__ */ React__default.createElement("li", { key: `${(_b2 = (_a3 = pod.metadata) == null ? void 0 : _a3.name) != null ? _b2 : "unknown"}-pf-${i}` }, fix);
2139
- })))), pf && pf.type === "logs" && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography$1, { variant: "h6" }, "Crash logs:")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 9 }, /* @__PURE__ */ React__default.createElement(
2140
- PodLogs,
2141
- {
2142
- previous: true,
2143
- containerScope: {
2144
- podName: (_f = (_e = pod.metadata) == null ? void 0 : _e.name) != null ? _f : "unknown",
2145
- podNamespace: (_h = (_g = pod.metadata) == null ? void 0 : _g.namespace) != null ? _h : "unknown",
2146
- clusterName,
2147
- containerName: pf.container
2148
- }
2149
- }
2150
- ))), pf && pf.type === "events" && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography$1, { variant: "h6" }, "Events:")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 9 }, /* @__PURE__ */ React__default.createElement(
2151
- Events,
2152
- {
2153
- warningEventsOnly: true,
2154
- involvedObjectName: (_j = (_i = pod.metadata) == null ? void 0 : _i.name) != null ? _j : "",
2155
- namespace: (_l = (_k = pod.metadata) == null ? void 0 : _k.namespace) != null ? _l : "",
2156
- clusterName
2157
- }
2158
- ))));
2159
- };
2160
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
2161
- Button,
2162
- {
2163
- variant: "outlined",
2164
- "aria-label": "fix issue",
2165
- component: "label",
2166
- onClick: openDialog,
2167
- startIcon: /* @__PURE__ */ React__default.createElement(HelpIcon, null)
2168
- },
2169
- "Help"
2170
- ), /* @__PURE__ */ React__default.createElement(Dialog$1, { maxWidth: "xl", fullWidth: true, open: isOpen, onClose: closeDialog }, /* @__PURE__ */ React__default.createElement(DialogTitle$1, { id: "dialog-title" }, (_a = pod.metadata) == null ? void 0 : _a.name, " - ", error.type, /* @__PURE__ */ React__default.createElement(
2171
- IconButton$1,
2172
- {
2173
- "aria-label": "close",
2174
- className: classes.closeButton,
2175
- onClick: closeDialog
2176
- },
2177
- /* @__PURE__ */ React__default.createElement(CloseIcon, null)
2178
- )), /* @__PURE__ */ React__default.createElement(DialogContent$1, null, dialogContent()), /* @__PURE__ */ React__default.createElement(DialogActions, null, pf && pf.type === "docs" && /* @__PURE__ */ React__default.createElement(
2179
- LinkButton,
2180
- {
2181
- to: pf.docsLink,
2182
- variant: "outlined",
2183
- startIcon: /* @__PURE__ */ React__default.createElement(OpenInNewIcon, null),
2184
- target: "_blank",
2185
- rel: "noopener"
2186
- },
2187
- "Open docs"
2188
- ))));
2189
- };
2190
-
2191
- const useStyles = makeStyles(
2192
- (_theme) => createStyles({
2193
- root: {
2194
- overflow: "auto"
2195
- },
2196
- list: {
2197
- width: "100%"
2198
- }
2199
- })
2200
- );
2201
- const ErrorList = ({ podAndErrors }) => {
2202
- const classes = useStyles();
2203
- return /* @__PURE__ */ React__default.createElement(Paper, { className: classes.root }, /* @__PURE__ */ React__default.createElement(List, { className: classes.list }, podAndErrors.filter((pae) => pae.errors.length > 0).flatMap((onlyPodWithErrors) => {
2204
- return onlyPodWithErrors.errors.map((error, i) => {
2205
- var _a, _b, _c;
2206
- return /* @__PURE__ */ React__default.createElement(
2207
- React__default.Fragment,
2208
- {
2209
- key: `${(_b = (_a = onlyPodWithErrors.pod.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown"}-eli-${i}`
2210
- },
2211
- i > 0 && /* @__PURE__ */ React__default.createElement(Divider, { key: `error-divider${i}` }),
2212
- /* @__PURE__ */ React__default.createElement(ListItem, null, /* @__PURE__ */ React__default.createElement(Grid, { container: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 9 }, /* @__PURE__ */ React__default.createElement(
2213
- ListItemText,
2214
- {
2215
- primary: error.message,
2216
- secondary: (_c = onlyPodWithErrors.pod.metadata) == null ? void 0 : _c.name
2217
- }
2218
- )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 3 }, /* @__PURE__ */ React__default.createElement(
2219
- FixDialog,
2220
- {
2221
- pod: onlyPodWithErrors.pod,
2222
- error,
2223
- clusterName: onlyPodWithErrors.clusterName
2224
- }
2225
- ))))
2226
- );
2227
- });
2228
- })));
2229
- };
2230
-
2231
- const useDrawerContentStyles = makeStyles(
2232
- (_theme) => createStyles({
2233
- header: {
2234
- display: "flex",
2235
- flexDirection: "row",
2236
- justifyContent: "space-between"
2237
- },
2238
- content: {
2239
- height: "80%"
2240
- },
2241
- icon: {
2242
- fontSize: 20
2243
- },
2244
- podoklist: {
2245
- width: "100%",
2246
- maxWidth: 360,
2247
- maxHeight: 360
2248
- }
2249
- })
2250
- );
2251
- function getContainerSpecByName(pod, containerName) {
2252
- var _a;
2253
- return (_a = pod.spec) == null ? void 0 : _a.containers.find((c) => c.name === containerName);
2254
- }
2255
- const PodDrawer = ({ podAndErrors, open }) => {
2256
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2257
- const classes = useDrawerContentStyles();
2258
- const podMetrics = usePodMetrics(podAndErrors.clusterName, podAndErrors.pod);
2259
- return /* @__PURE__ */ React__default.createElement(
2260
- KubernetesDrawer,
2261
- {
2262
- open,
2263
- drawerContentsHeader: /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle1" }, "Pod", " ", ((_a = podAndErrors.pod.status) == null ? void 0 : _a.podIP) && `(${(_b = podAndErrors.pod.status) == null ? void 0 : _b.podIP})`),
2264
- kubernetesObject: podAndErrors.pod,
2265
- label: /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle1" }, (_d = (_c = podAndErrors.pod.metadata) == null ? void 0 : _c.name) != null ? _d : "unknown")
2266
- },
2267
- /* @__PURE__ */ React__default.createElement("div", { className: classes.content }, podMetrics && /* @__PURE__ */ React__default.createElement(Grid, { container: true, item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, "Resource utilization")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React__default.createElement(
2268
- ResourceUtilization,
2269
- {
2270
- title: "CPU requests",
2271
- usage: podMetrics.cpu.currentUsage,
2272
- total: podMetrics.cpu.requestTotal,
2273
- totalFormatted: formatMillicores(podMetrics.cpu.requestTotal)
2274
- }
2275
- ), /* @__PURE__ */ React__default.createElement(
2276
- ResourceUtilization,
2277
- {
2278
- title: "CPU limits",
2279
- usage: podMetrics.cpu.currentUsage,
2280
- total: podMetrics.cpu.limitTotal,
2281
- totalFormatted: formatMillicores(podMetrics.cpu.limitTotal)
2282
- }
2283
- )), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React__default.createElement(
2284
- ResourceUtilization,
2285
- {
2286
- title: "Memory requests",
2287
- usage: podMetrics.memory.currentUsage,
2288
- total: podMetrics.memory.requestTotal,
2289
- totalFormatted: bytesToMiB(podMetrics.memory.requestTotal)
2290
- }
2291
- ), /* @__PURE__ */ React__default.createElement(
2292
- ResourceUtilization,
2293
- {
2294
- title: "Memory limits",
2295
- usage: podMetrics.memory.currentUsage,
2296
- total: podMetrics.memory.limitTotal,
2297
- totalFormatted: bytesToMiB(podMetrics.memory.requestTotal)
2298
- }
2299
- ))), ((_e = podAndErrors.pod.status) == null ? void 0 : _e.phase) === "Pending" && /* @__PURE__ */ React__default.createElement(PendingPodContent, { pod: podAndErrors.pod }), ((_g = (_f = podAndErrors.pod.status) == null ? void 0 : _f.containerStatuses) == null ? void 0 : _g.length) && /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, "Containers")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(ItemCardGrid, null, (_i = (_h = podAndErrors.pod.status) == null ? void 0 : _h.containerStatuses) == null ? void 0 : _i.map(
2300
- (containerStatus, i) => {
2301
- var _a2, _b2, _c2, _d2, _e2, _f2;
2302
- const containerSpec = getContainerSpecByName(
2303
- podAndErrors.pod,
2304
- containerStatus.name
2305
- );
2306
- const containerMetrics = ((_a2 = podMetrics == null ? void 0 : podMetrics.containers) != null ? _a2 : []).find((c) => c.container === containerStatus.name);
2307
- return /* @__PURE__ */ React__default.createElement(
2308
- ContainerCard,
2309
- {
2310
- key: `container-card-${(_b2 = podAndErrors.pod.metadata) == null ? void 0 : _b2.name}-${i}`,
2311
- containerMetrics,
2312
- podScope: {
2313
- podName: (_d2 = (_c2 = podAndErrors.pod.metadata) == null ? void 0 : _c2.name) != null ? _d2 : "unknown",
2314
- podNamespace: (_f2 = (_e2 = podAndErrors.pod.metadata) == null ? void 0 : _e2.namespace) != null ? _f2 : "unknown",
2315
- clusterName: podAndErrors.clusterName
2316
- },
2317
- containerSpec,
2318
- containerStatus
2319
- }
2320
- );
2321
- }
2322
- ))), podAndErrors.errors.length > 0 && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, "Errors")), podAndErrors.errors.length > 0 && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React__default.createElement(ErrorList, { podAndErrors: [podAndErrors] }))))
2323
- );
2324
- };
2325
-
2326
- const containersReady = (pod) => {
2327
- var _a, _b;
2328
- const containerStatuses2 = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
2329
- const containersReadyItem = containerStatuses2.filter((cs) => cs.ready).length;
2330
- return `${containersReadyItem}/${containerStatuses2.length}`;
2331
- };
2332
- const totalRestarts = (pod) => {
2333
- var _a, _b;
2334
- const containerStatuses2 = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
2335
- return containerStatuses2 == null ? void 0 : containerStatuses2.reduce((a, b) => a + b.restartCount, 0);
2336
- };
2337
- const containerStatuses = (pod) => {
2338
- var _a, _b;
2339
- const containerStatusesItem = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
2340
- const errors = containerStatusesItem.reduce((accum, next) => {
2341
- if (next.state === void 0) {
2342
- return accum;
2343
- }
2344
- const waiting = next.state.waiting;
2345
- const terminated = next.state.terminated;
2346
- const renderCell = (reason) => {
2347
- var _a2;
2348
- return /* @__PURE__ */ React__default.createElement(Fragment, { key: `${(_a2 = pod.metadata) == null ? void 0 : _a2.name}-${next.name}` }, /* @__PURE__ */ React__default.createElement(
2349
- SubvalueCell,
2350
- {
2351
- value: reason === "Completed" ? /* @__PURE__ */ React__default.createElement(StatusOK, null, "Container: ", next.name) : /* @__PURE__ */ React__default.createElement(StatusError, null, "Container: ", next.name),
2352
- subvalue: reason
2353
- }
2354
- ), /* @__PURE__ */ React__default.createElement("br", null));
2355
- };
2356
- if (waiting) {
2357
- accum.push(renderCell(waiting.reason));
2358
- }
2359
- if (terminated) {
2360
- accum.push(renderCell(terminated.reason));
2361
- }
2362
- return accum;
2363
- }, []);
2364
- if (errors.length === 0) {
2365
- return /* @__PURE__ */ React__default.createElement(StatusOK, null, "OK");
2366
- }
2367
- return errors;
2368
- };
2369
- const renderCondition = (condition) => {
2370
- var _a;
2371
- const status = condition.status;
2372
- if (status === "True") {
2373
- return [condition.type, /* @__PURE__ */ React__default.createElement(StatusOK, null, "True")];
2374
- } else if (status === "False") {
2375
- return [
2376
- condition.type,
2377
- /* @__PURE__ */ React__default.createElement(
2378
- SubvalueCell,
2379
- {
2380
- value: /* @__PURE__ */ React__default.createElement(StatusError, null, "False"),
2381
- subvalue: (_a = condition.message) != null ? _a : ""
2382
- }
2383
- )
2384
- ];
2385
- }
2386
- return [condition.type, /* @__PURE__ */ React__default.createElement(StatusAborted, null)];
2387
- };
2388
- const currentToDeclaredResourceToPerc = (current, resource) => {
2389
- if (Number(resource) === 0)
2390
- return `0%`;
2391
- if (typeof current === "number" && typeof resource === "number") {
2392
- return `${Math.round(current / resource * 100)}%`;
2393
- }
2394
- const numerator = BigInt(current);
2395
- const denominator = BigInt(resource);
2396
- return `${numerator * BigInt(100) / denominator}%`;
2397
- };
2398
- const podStatusToCpuUtil = (podStatus) => {
2399
- const cpuUtil = podStatus.cpu;
2400
- let currentUsage = cpuUtil.currentUsage;
2401
- if (typeof cpuUtil.currentUsage === "number") {
2402
- currentUsage = cpuUtil.currentUsage / 10;
2403
- }
2404
- return /* @__PURE__ */ React__default.createElement(
2405
- SubvalueCell,
2406
- {
2407
- value: `requests: ${currentToDeclaredResourceToPerc(
2408
- currentUsage,
2409
- cpuUtil.requestTotal
2410
- )} of ${formatMillicores(cpuUtil.requestTotal)}`,
2411
- subvalue: `limits: ${currentToDeclaredResourceToPerc(
2412
- currentUsage,
2413
- cpuUtil.limitTotal
2414
- )} of ${formatMillicores(cpuUtil.limitTotal)}`
2415
- }
2416
- );
2417
- };
2418
- const podStatusToMemoryUtil = (podStatus) => {
2419
- const memUtil = podStatus.memory;
2420
- return /* @__PURE__ */ React__default.createElement(
2421
- SubvalueCell,
2422
- {
2423
- value: `requests: ${currentToDeclaredResourceToPerc(
2424
- memUtil.currentUsage,
2425
- memUtil.requestTotal
2426
- )} of ${bytesToMiB(memUtil.requestTotal)}`,
2427
- subvalue: `limits: ${currentToDeclaredResourceToPerc(
2428
- memUtil.currentUsage,
2429
- memUtil.limitTotal
2430
- )} of ${bytesToMiB(memUtil.limitTotal)}`
2431
- }
2432
- );
2433
- };
2434
-
2435
- const READY_COLUMNS = "READY";
2436
- const RESOURCE_COLUMNS = "RESOURCE";
2437
- const READY = [
2438
- {
2439
- title: "containers ready",
2440
- align: "center",
2441
- render: containersReady,
2442
- width: "auto"
2443
- },
2444
- {
2445
- title: "total restarts",
2446
- align: "center",
2447
- render: totalRestarts,
2448
- type: "numeric",
2449
- width: "auto"
2450
- }
2451
- ];
2452
- const PodDrawerTrigger = ({ pod }) => {
2453
- const cluster = useContext(ClusterContext);
2454
- const errors = useMatchingErrors({
2455
- kind: "Pod",
2456
- apiVersion: "v1",
2457
- metadata: pod.metadata
2458
- });
2459
- return /* @__PURE__ */ React__default.createElement(
2460
- PodDrawer,
2461
- {
2462
- podAndErrors: {
2463
- pod,
2464
- clusterName: cluster.name,
2465
- errors
2466
- }
2467
- }
2468
- );
2469
- };
2470
- const Cpu = ({ clusterName, pod }) => {
2471
- const metrics = usePodMetrics(clusterName, pod);
2472
- if (!metrics) {
2473
- return /* @__PURE__ */ React__default.createElement(Typography, null, "unknown");
2474
- }
2475
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, podStatusToCpuUtil(metrics));
2476
- };
2477
- const Memory = ({ clusterName, pod }) => {
2478
- const metrics = usePodMetrics(clusterName, pod);
2479
- if (!metrics) {
2480
- return /* @__PURE__ */ React__default.createElement(Typography, null, "unknown");
2481
- }
2482
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, podStatusToMemoryUtil(metrics));
2483
- };
2484
- const PodsTable = ({ pods, extraColumns = [] }) => {
2485
- const cluster = useContext(ClusterContext);
2486
- const defaultColumns = [
2487
- {
2488
- title: "name",
2489
- highlight: true,
2490
- render: (pod) => {
2491
- return /* @__PURE__ */ React__default.createElement(PodDrawerTrigger, { pod });
2492
- }
2493
- },
2494
- {
2495
- title: "phase",
2496
- render: (pod) => {
2497
- var _a, _b;
2498
- return (_b = (_a = pod.status) == null ? void 0 : _a.phase) != null ? _b : "unknown";
2499
- },
2500
- width: "auto"
2501
- },
2502
- {
2503
- title: "status",
2504
- render: containerStatuses
2505
- }
2506
- ];
2507
- const columns = [...defaultColumns];
2508
- if (extraColumns.includes(READY_COLUMNS)) {
2509
- columns.push(...READY);
2510
- }
2511
- if (extraColumns.includes(RESOURCE_COLUMNS)) {
2512
- const resourceColumns = [
2513
- {
2514
- title: "CPU usage %",
2515
- render: (pod) => {
2516
- return /* @__PURE__ */ React__default.createElement(Cpu, { clusterName: cluster.name, pod });
2517
- },
2518
- width: "auto"
2519
- },
2520
- {
2521
- title: "Memory usage %",
2522
- render: (pod) => {
2523
- return /* @__PURE__ */ React__default.createElement(Memory, { clusterName: cluster.name, pod });
2524
- },
2525
- width: "auto"
2526
- }
2527
- ];
2528
- columns.push(...resourceColumns);
2529
- }
2530
- const tableStyle = {
2531
- minWidth: "0",
2532
- width: "100%"
2533
- };
2534
- return /* @__PURE__ */ React__default.createElement("div", { style: tableStyle }, /* @__PURE__ */ React__default.createElement(
2535
- Table,
2536
- {
2537
- options: { paging: true, search: false, emptyRowsWhenPaging: false },
2538
- data: pods,
2539
- columns
2540
- }
2541
- ));
2542
- };
2543
-
2544
- const DeploymentDrawer = ({
2545
- deployment,
2546
- expanded
2547
- }) => {
2548
- var _a, _b, _c;
2549
- const namespace = (_a = deployment.metadata) == null ? void 0 : _a.namespace;
2550
- return /* @__PURE__ */ React__default.createElement(
2551
- KubernetesStructuredMetadataTableDrawer,
2552
- {
2553
- object: deployment,
2554
- expanded,
2555
- kind: "Deployment",
2556
- renderObject: (deploymentObj) => {
2557
- var _a2, _b2, _c2, _d, _e, _f, _g, _h;
2558
- const conditions = ((_b2 = (_a2 = deploymentObj.status) == null ? void 0 : _a2.conditions) != null ? _b2 : []).map(renderCondition).reduce((accum, next) => {
2559
- accum[next[0]] = next[1];
2560
- return accum;
2561
- }, {});
2562
- return {
2563
- strategy: (_d = (_c2 = deploymentObj.spec) == null ? void 0 : _c2.strategy) != null ? _d : "???",
2564
- minReadySeconds: (_f = (_e = deploymentObj.spec) == null ? void 0 : _e.minReadySeconds) != null ? _f : "???",
2565
- progressDeadlineSeconds: (_h = (_g = deploymentObj.spec) == null ? void 0 : _g.progressDeadlineSeconds) != null ? _h : "???",
2566
- ...conditions
2567
- };
2568
- }
2569
- },
2570
- /* @__PURE__ */ React__default.createElement(
2571
- Grid,
2572
- {
2573
- container: true,
2574
- direction: "column",
2575
- justifyContent: "flex-start",
2576
- alignItems: "flex-start",
2577
- spacing: 0
2578
- },
2579
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, (_c = (_b = deployment.metadata) == null ? void 0 : _b.name) != null ? _c : "unknown object")),
2580
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, "Deployment")),
2581
- namespace && /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Chip, { size: "small", label: `namespace: ${namespace}` }))
2582
- )
2583
- );
2584
- };
2585
-
2586
- const HorizontalPodAutoscalerDrawer = (props) => {
2587
- const { hpa, expanded, children } = props;
2588
- return /* @__PURE__ */ React__default.createElement(
2589
- KubernetesStructuredMetadataTableDrawer,
2590
- {
2591
- kind: "HorizontalPodAutoscaler",
2592
- object: hpa,
2593
- expanded,
2594
- renderObject: (hpaObject) => {
2595
- var _a, _b, _c, _d, _e, _f;
2596
- return {
2597
- targetCPUUtilizationPercentage: (_a = hpaObject.spec) == null ? void 0 : _a.targetCPUUtilizationPercentage,
2598
- currentCPUUtilizationPercentage: (_b = hpaObject.status) == null ? void 0 : _b.currentCPUUtilizationPercentage,
2599
- minReplicas: (_c = hpaObject.spec) == null ? void 0 : _c.minReplicas,
2600
- maxReplicas: (_d = hpaObject.spec) == null ? void 0 : _d.maxReplicas,
2601
- currentReplicas: (_e = hpaObject.status) == null ? void 0 : _e.currentReplicas,
2602
- desiredReplicas: (_f = hpaObject.status) == null ? void 0 : _f.desiredReplicas
2603
- };
2604
- }
2605
- },
2606
- children
2607
- );
2608
- };
2609
-
2610
- function getOwnedResources(potentialOwner, possiblyOwned) {
2611
- return possiblyOwned.filter(
2612
- (p) => {
2613
- var _a, _b, _c;
2614
- return (_c = (_b = (_a = p.metadata) == null ? void 0 : _a.ownerReferences) == null ? void 0 : _b.some(
2615
- (o) => {
2616
- var _a2;
2617
- return o.uid === ((_a2 = potentialOwner.metadata) == null ? void 0 : _a2.uid);
2618
- }
2619
- )) != null ? _c : false;
2620
- }
2621
- );
2622
- }
2623
- const getOwnedPodsThroughReplicaSets = (potentialOwner, replicaSets, pods) => {
2624
- return getOwnedResources(
2625
- potentialOwner,
2626
- replicaSets.filter((rs) => rs.status && rs.status.replicas > 0)
2627
- ).reduce((accum, rs) => {
2628
- return accum.concat(getOwnedResources(rs, pods));
2629
- }, []);
2630
- };
2631
- const getMatchingHpa = (owner, hpas) => {
2632
- return hpas.find((hpa) => {
2633
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2634
- return ((_c = (_b = (_a = hpa.spec) == null ? void 0 : _a.scaleTargetRef) == null ? void 0 : _b.kind) != null ? _c : "").toLocaleLowerCase("en-US") === owner.kind.toLocaleLowerCase("en-US") && ((_e = (_d = hpa.metadata) == null ? void 0 : _d.namespace) != null ? _e : "") === ((_f = owner.namespace) != null ? _f : "unknown-namespace") && ((_i = (_h = (_g = hpa.spec) == null ? void 0 : _g.scaleTargetRef) == null ? void 0 : _h.name) != null ? _i : "") === ((_j = owner.name) != null ? _j : "unknown-deployment");
2635
- });
2636
- };
2637
-
2638
- const DeploymentSummary = ({
2639
- deployment,
2640
- numberOfCurrentPods,
2641
- numberOfPodsWithErrors,
2642
- hpa
2643
- }) => {
2644
- var _a, _b, _c, _d, _e, _f, _g, _h;
2645
- return /* @__PURE__ */ React__default.createElement(
2646
- Grid,
2647
- {
2648
- container: true,
2649
- direction: "row",
2650
- justifyContent: "space-between",
2651
- alignItems: "center",
2652
- spacing: 0
2653
- },
2654
- /* @__PURE__ */ React__default.createElement(Grid, { xs: 4, item: true }, /* @__PURE__ */ React__default.createElement(DeploymentDrawer, { deployment })),
2655
- hpa && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 4 }, /* @__PURE__ */ React__default.createElement(HorizontalPodAutoscalerDrawer, { hpa }, /* @__PURE__ */ React__default.createElement(
2656
- Grid,
2657
- {
2658
- item: true,
2659
- container: true,
2660
- direction: "column",
2661
- justifyContent: "flex-start",
2662
- alignItems: "flex-start",
2663
- spacing: 0
2664
- },
2665
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "min replicas ", (_b = (_a = hpa.spec) == null ? void 0 : _a.minReplicas) != null ? _b : "?", " / max replicas", " ", (_d = (_c = hpa.spec) == null ? void 0 : _c.maxReplicas) != null ? _d : "?")),
2666
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "current CPU usage:", " ", (_f = (_e = hpa.status) == null ? void 0 : _e.currentCPUUtilizationPercentage) != null ? _f : "?", "%")),
2667
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "target CPU usage:", " ", (_h = (_g = hpa.spec) == null ? void 0 : _g.targetCPUUtilizationPercentage) != null ? _h : "?", "%"))
2668
- ))),
2669
- /* @__PURE__ */ React__default.createElement(
2670
- Grid,
2671
- {
2672
- item: true,
2673
- container: true,
2674
- xs: 4,
2675
- direction: "column",
2676
- justifyContent: "flex-start",
2677
- alignItems: "flex-end",
2678
- spacing: 0
2679
- },
2680
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(StatusOK, null, numberOfCurrentPods, " pods")),
2681
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, numberOfPodsWithErrors > 0 ? /* @__PURE__ */ React__default.createElement(StatusError, null, numberOfPodsWithErrors, " pod", numberOfPodsWithErrors > 1 ? "s" : "", " with errors") : /* @__PURE__ */ React__default.createElement(StatusOK, null, "No pods with errors"))
2682
- )
2683
- );
2684
- };
2685
- const DeploymentAccordion = ({
2686
- deployment,
2687
- ownedPods,
2688
- matchingHpa
2689
- }) => {
2690
- const podNamesWithErrors = useContext(PodNamesWithErrorsContext);
2691
- const podsWithErrors = ownedPods.filter(
2692
- (p) => {
2693
- var _a, _b;
2694
- return podNamesWithErrors.has((_b = (_a = p.metadata) == null ? void 0 : _a.name) != null ? _b : "");
2695
- }
2696
- );
2697
- return /* @__PURE__ */ React__default.createElement(Accordion, { TransitionProps: { unmountOnExit: true }, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(
2698
- DeploymentSummary,
2699
- {
2700
- deployment,
2701
- numberOfCurrentPods: ownedPods.length,
2702
- numberOfPodsWithErrors: podsWithErrors.length,
2703
- hpa: matchingHpa
2704
- }
2705
- )), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(
2706
- PodsTable,
2707
- {
2708
- pods: ownedPods,
2709
- extraColumns: [READY_COLUMNS, RESOURCE_COLUMNS]
2710
- }
2711
- )));
2712
- };
2713
- const DeploymentsAccordions = ({}) => {
2714
- const groupedResponses = useContext(GroupedResponsesContext);
2715
- return /* @__PURE__ */ React__default.createElement(
2716
- Grid,
2717
- {
2718
- container: true,
2719
- direction: "column",
2720
- justifyContent: "flex-start",
2721
- alignItems: "flex-start"
2722
- },
2723
- groupedResponses.deployments.map((deployment, i) => {
2724
- var _a, _b;
2725
- return /* @__PURE__ */ React__default.createElement(Grid, { container: true, item: true, key: i, xs: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: true }, /* @__PURE__ */ React__default.createElement(
2726
- DeploymentAccordion,
2727
- {
2728
- matchingHpa: getMatchingHpa(
2729
- {
2730
- name: (_a = deployment.metadata) == null ? void 0 : _a.name,
2731
- namespace: (_b = deployment.metadata) == null ? void 0 : _b.namespace,
2732
- kind: "deployment"
2733
- },
2734
- groupedResponses.horizontalPodAutoscalers
2735
- ),
2736
- ownedPods: getOwnedPodsThroughReplicaSets(
2737
- deployment,
2738
- groupedResponses.replicaSets,
2739
- groupedResponses.pods
2740
- ),
2741
- deployment
2742
- }
2743
- )));
2744
- })
2745
- );
2746
- };
2747
-
2748
- const StatefulSetDrawer = ({
2749
- statefulset,
2750
- expanded
2751
- }) => {
2752
- var _a, _b, _c;
2753
- const namespace = (_a = statefulset.metadata) == null ? void 0 : _a.namespace;
2754
- return /* @__PURE__ */ React__default.createElement(
2755
- KubernetesStructuredMetadataTableDrawer,
2756
- {
2757
- object: statefulset,
2758
- expanded,
2759
- kind: "StatefulSet",
2760
- renderObject: (statefulsetObj) => {
2761
- var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j, _k, _l;
2762
- const conditions = ((_b2 = (_a2 = statefulsetObj.status) == null ? void 0 : _a2.conditions) != null ? _b2 : []).map(renderCondition).reduce((accum, next) => {
2763
- accum[next[0]] = next[1];
2764
- return accum;
2765
- }, {});
2766
- return {
2767
- updateStrategy: (_d = (_c2 = statefulset.spec) == null ? void 0 : _c2.updateStrategy) != null ? _d : "???",
2768
- podManagementPolicy: (_f = (_e = statefulset.spec) == null ? void 0 : _e.podManagementPolicy) != null ? _f : "???",
2769
- serviceName: (_h = (_g = statefulset.spec) == null ? void 0 : _g.serviceName) != null ? _h : "???",
2770
- selector: (_j = (_i = statefulset.spec) == null ? void 0 : _i.selector) != null ? _j : "???",
2771
- revisionHistoryLimit: (_l = (_k = statefulset.spec) == null ? void 0 : _k.revisionHistoryLimit) != null ? _l : "???",
2772
- ...conditions
2773
- };
2774
- }
2775
- },
2776
- /* @__PURE__ */ React__default.createElement(
2777
- Grid,
2778
- {
2779
- container: true,
2780
- direction: "column",
2781
- justifyContent: "flex-start",
2782
- alignItems: "flex-start",
2783
- spacing: 0
2784
- },
2785
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, (_c = (_b = statefulset.metadata) == null ? void 0 : _b.name) != null ? _c : "unknown object")),
2786
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, "Stateful Set")),
2787
- namespace && /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Chip, { size: "small", label: `namespace: ${namespace}` }))
2788
- )
2789
- );
2790
- };
2791
-
2792
- const StatefulSetSummary = ({
2793
- statefulset,
2794
- numberOfCurrentPods,
2795
- numberOfPodsWithErrors,
2796
- hpa
2797
- }) => {
2798
- var _a, _b, _c, _d, _e, _f, _g, _h;
2799
- return /* @__PURE__ */ React__default.createElement(
2800
- Grid,
2801
- {
2802
- container: true,
2803
- direction: "row",
2804
- justifyContent: "space-between",
2805
- alignItems: "center",
2806
- spacing: 0
2807
- },
2808
- /* @__PURE__ */ React__default.createElement(Grid, { xs: 6, item: true }, /* @__PURE__ */ React__default.createElement(StatefulSetDrawer, { statefulset })),
2809
- hpa && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 3 }, /* @__PURE__ */ React__default.createElement(HorizontalPodAutoscalerDrawer, { hpa }, /* @__PURE__ */ React__default.createElement(
2810
- Grid,
2811
- {
2812
- item: true,
2813
- container: true,
2814
- direction: "column",
2815
- justifyContent: "flex-start",
2816
- alignItems: "flex-start",
2817
- spacing: 0
2818
- },
2819
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "min replicas ", (_b = (_a = hpa.spec) == null ? void 0 : _a.minReplicas) != null ? _b : "?", " / max replicas", " ", (_d = (_c = hpa.spec) == null ? void 0 : _c.maxReplicas) != null ? _d : "?")),
2820
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "current CPU usage:", " ", (_f = (_e = hpa.status) == null ? void 0 : _e.currentCPUUtilizationPercentage) != null ? _f : "?", "%")),
2821
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "target CPU usage:", " ", (_h = (_g = hpa.spec) == null ? void 0 : _g.targetCPUUtilizationPercentage) != null ? _h : "?", "%"))
2822
- ))),
2823
- /* @__PURE__ */ React__default.createElement(
2824
- Grid,
2825
- {
2826
- item: true,
2827
- container: true,
2828
- xs: 3,
2829
- direction: "column",
2830
- justifyContent: "flex-start",
2831
- alignItems: "flex-start",
2832
- spacing: 0
2833
- },
2834
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(StatusOK, null, numberOfCurrentPods, " pods")),
2835
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, numberOfPodsWithErrors > 0 ? /* @__PURE__ */ React__default.createElement(StatusError, null, numberOfPodsWithErrors, " pod", numberOfPodsWithErrors > 1 ? "s" : "", " with errors") : /* @__PURE__ */ React__default.createElement(StatusOK, null, "No pods with errors"))
2836
- )
2837
- );
2838
- };
2839
- const StatefulSetAccordion = ({
2840
- statefulset,
2841
- ownedPods,
2842
- matchingHpa
2843
- }) => {
2844
- const podNamesWithErrors = useContext(PodNamesWithErrorsContext);
2845
- const podsWithErrors = ownedPods.filter(
2846
- (p) => {
2847
- var _a, _b;
2848
- return podNamesWithErrors.has((_b = (_a = p.metadata) == null ? void 0 : _a.name) != null ? _b : "");
2849
- }
2850
- );
2851
- return /* @__PURE__ */ React__default.createElement(Accordion, { TransitionProps: { unmountOnExit: true }, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(
2852
- StatefulSetSummary,
2853
- {
2854
- statefulset,
2855
- numberOfCurrentPods: ownedPods.length,
2856
- numberOfPodsWithErrors: podsWithErrors.length,
2857
- hpa: matchingHpa
2858
- }
2859
- )), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(
2860
- PodsTable,
2861
- {
2862
- pods: ownedPods,
2863
- extraColumns: [READY_COLUMNS, RESOURCE_COLUMNS]
2864
- }
2865
- )));
2866
- };
2867
- const StatefulSetsAccordions = ({}) => {
2868
- const groupedResponses = useContext(GroupedResponsesContext);
2869
- return /* @__PURE__ */ React__default.createElement(
2870
- Grid,
2871
- {
2872
- container: true,
2873
- direction: "column",
2874
- justifyContent: "flex-start",
2875
- alignItems: "flex-start"
2876
- },
2877
- groupedResponses.statefulsets.map((statefulset, i) => {
2878
- var _a, _b;
2879
- return /* @__PURE__ */ React__default.createElement(Grid, { container: true, item: true, key: i, xs: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: true }, /* @__PURE__ */ React__default.createElement(
2880
- StatefulSetAccordion,
2881
- {
2882
- matchingHpa: getMatchingHpa(
2883
- {
2884
- name: (_a = statefulset.metadata) == null ? void 0 : _a.name,
2885
- namespace: (_b = statefulset.metadata) == null ? void 0 : _b.namespace,
2886
- kind: "statefulset"
2887
- },
2888
- groupedResponses.horizontalPodAutoscalers
2889
- ),
2890
- ownedPods: getOwnedResources(statefulset, groupedResponses.pods),
2891
- statefulset
2892
- }
2893
- )));
2894
- })
2895
- );
2896
- };
2897
-
2898
- const IngressDrawer = ({
2899
- ingress,
2900
- expanded
2901
- }) => {
2902
- var _a, _b;
2903
- return /* @__PURE__ */ React__default.createElement(
2904
- KubernetesStructuredMetadataTableDrawer,
2905
- {
2906
- object: ingress,
2907
- expanded,
2908
- kind: "Ingress",
2909
- renderObject: (ingressObject) => {
2910
- return ingressObject.spec || {};
2911
- }
2912
- },
2913
- /* @__PURE__ */ React__default.createElement(
2914
- Grid,
2915
- {
2916
- container: true,
2917
- direction: "column",
2918
- justifyContent: "flex-start",
2919
- alignItems: "flex-start",
2920
- spacing: 0
2921
- },
2922
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, (_b = (_a = ingress.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown object")),
2923
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, "Ingress"))
2924
- )
2925
- );
2926
- };
2927
-
2928
- const IngressSummary = ({ ingress }) => {
2929
- return /* @__PURE__ */ React__default.createElement(
2930
- Grid,
2931
- {
2932
- container: true,
2933
- direction: "row",
2934
- justifyContent: "flex-start",
2935
- alignItems: "center"
2936
- },
2937
- /* @__PURE__ */ React__default.createElement(Grid, { xs: 12, item: true }, /* @__PURE__ */ React__default.createElement(IngressDrawer, { ingress }))
2938
- );
2939
- };
2940
- const IngressCard = ({ ingress }) => {
2941
- return /* @__PURE__ */ React__default.createElement(
2942
- StructuredMetadataTable,
2943
- {
2944
- metadata: {
2945
- ...ingress.spec
2946
- }
2947
- }
2948
- );
2949
- };
2950
- const IngressAccordion = ({ ingress }) => {
2951
- return /* @__PURE__ */ React__default.createElement(Accordion, { TransitionProps: { unmountOnExit: true } }, /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(IngressSummary, { ingress })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(IngressCard, { ingress })));
2952
- };
2953
- const IngressesAccordions = ({}) => {
2954
- const groupedResponses = useContext(GroupedResponsesContext);
2955
- return /* @__PURE__ */ React__default.createElement(
2956
- Grid,
2957
- {
2958
- container: true,
2959
- direction: "row",
2960
- justifyContent: "flex-start",
2961
- alignItems: "flex-start"
2962
- },
2963
- groupedResponses.ingresses.map((ingress, i) => /* @__PURE__ */ React__default.createElement(Grid, { item: true, key: i, xs: true }, /* @__PURE__ */ React__default.createElement(IngressAccordion, { ingress })))
2964
- );
2965
- };
2966
-
2967
- const ServiceDrawer = ({
2968
- service,
2969
- expanded
2970
- }) => {
2971
- var _a, _b;
2972
- return /* @__PURE__ */ React__default.createElement(
2973
- KubernetesStructuredMetadataTableDrawer,
2974
- {
2975
- object: service,
2976
- expanded,
2977
- kind: "Service",
2978
- renderObject: (serviceObject) => {
2979
- return serviceObject.spec || {};
2980
- }
2981
- },
2982
- /* @__PURE__ */ React__default.createElement(
2983
- Grid,
2984
- {
2985
- container: true,
2986
- direction: "column",
2987
- justifyContent: "flex-start",
2988
- alignItems: "flex-start",
2989
- spacing: 0
2990
- },
2991
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, (_b = (_a = service.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown object")),
2992
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, "Service"))
2993
- )
2994
- );
2995
- };
2996
-
2997
- const ServiceSummary = ({ service }) => {
2998
- var _a, _b;
2999
- return /* @__PURE__ */ React__default.createElement(
3000
- Grid,
3001
- {
3002
- container: true,
3003
- direction: "row",
3004
- justifyContent: "space-between",
3005
- alignItems: "center",
3006
- spacing: 0
3007
- },
3008
- /* @__PURE__ */ React__default.createElement(Grid, { xs: 8, item: true }, /* @__PURE__ */ React__default.createElement(ServiceDrawer, { service })),
3009
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "Type: ", (_b = (_a = service.spec) == null ? void 0 : _a.type) != null ? _b : "?"))
3010
- );
3011
- };
3012
- const ServiceCard = ({ service }) => {
3013
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
3014
- const metadata = {};
3015
- if ((_d = (_c = (_b = (_a = service.status) == null ? void 0 : _a.loadBalancer) == null ? void 0 : _b.ingress) == null ? void 0 : _c.length) != null ? _d : -1 > 0) {
3016
- metadata.loadbalancer = (_e = service.status) == null ? void 0 : _e.loadBalancer;
3017
- }
3018
- if (((_f = service.spec) == null ? void 0 : _f.type) === "ClusterIP") {
3019
- metadata.clusterIP = service.spec.clusterIP;
3020
- }
3021
- if (((_g = service.spec) == null ? void 0 : _g.type) === "ExternalName") {
3022
- metadata.externalName = service.spec.externalName;
3023
- }
3024
- return /* @__PURE__ */ React__default.createElement(
3025
- StructuredMetadataTable,
3026
- {
3027
- metadata: {
3028
- type: (_h = service.spec) == null ? void 0 : _h.type,
3029
- ports: (_i = service.spec) == null ? void 0 : _i.ports,
3030
- ...metadata
3031
- }
3032
- }
3033
- );
3034
- };
3035
- const ServiceAccordion = ({ service }) => {
3036
- return /* @__PURE__ */ React__default.createElement(Accordion, { TransitionProps: { unmountOnExit: true }, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(ServiceSummary, { service })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(ServiceCard, { service })));
3037
- };
3038
- const ServicesAccordions = ({}) => {
3039
- const groupedResponses = useContext(GroupedResponsesContext);
3040
- return /* @__PURE__ */ React__default.createElement(
3041
- Grid,
3042
- {
3043
- container: true,
3044
- direction: "row",
3045
- justifyContent: "flex-start",
3046
- alignItems: "flex-start"
3047
- },
3048
- groupedResponses.services.map((service, i) => /* @__PURE__ */ React__default.createElement(Grid, { item: true, key: i, xs: true }, /* @__PURE__ */ React__default.createElement(ServiceAccordion, { service })))
3049
- );
3050
- };
3051
-
3052
- const JobDrawer = ({
3053
- job,
3054
- expanded
3055
- }) => {
3056
- var _a, _b;
3057
- return /* @__PURE__ */ React__default.createElement(
3058
- KubernetesStructuredMetadataTableDrawer,
3059
- {
3060
- object: job,
3061
- expanded,
3062
- kind: "Job",
3063
- renderObject: (jobObj) => {
3064
- var _a2, _b2, _c, _d, _e, _f, _g, _h;
3065
- return {
3066
- parallelism: (_b2 = (_a2 = jobObj.spec) == null ? void 0 : _a2.parallelism) != null ? _b2 : "???",
3067
- completions: (_d = (_c = jobObj.spec) == null ? void 0 : _c.completions) != null ? _d : "???",
3068
- backoffLimit: (_f = (_e = jobObj.spec) == null ? void 0 : _e.backoffLimit) != null ? _f : "???",
3069
- startTime: (_h = (_g = jobObj.status) == null ? void 0 : _g.startTime) != null ? _h : "???"
3070
- };
3071
- }
3072
- },
3073
- /* @__PURE__ */ React__default.createElement(
3074
- Grid,
3075
- {
3076
- container: true,
3077
- direction: "column",
3078
- justifyContent: "flex-start",
3079
- alignItems: "flex-start",
3080
- spacing: 0
3081
- },
3082
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, (_b = (_a = job.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown object")),
3083
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, "Job"))
3084
- )
3085
- );
3086
- };
3087
-
3088
- const JobSummary = ({ job }) => {
3089
- var _a, _b, _c, _d, _e, _f;
3090
- return /* @__PURE__ */ React__default.createElement(
3091
- Grid,
3092
- {
3093
- container: true,
3094
- direction: "row",
3095
- justifyContent: "space-between",
3096
- alignItems: "center",
3097
- spacing: 0
3098
- },
3099
- /* @__PURE__ */ React__default.createElement(Grid, { xs: 6, item: true }, /* @__PURE__ */ React__default.createElement(JobDrawer, { job })),
3100
- /* @__PURE__ */ React__default.createElement(
3101
- Grid,
3102
- {
3103
- item: true,
3104
- container: true,
3105
- xs: 6,
3106
- direction: "column",
3107
- justifyContent: "flex-start",
3108
- alignItems: "flex-end",
3109
- spacing: 0
3110
- },
3111
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, ((_a = job.status) == null ? void 0 : _a.succeeded) && /* @__PURE__ */ React__default.createElement(StatusOK, null, "Succeeded"), ((_b = job.status) == null ? void 0 : _b.active) && /* @__PURE__ */ React__default.createElement(StatusPending, null, "Running"), ((_c = job.status) == null ? void 0 : _c.failed) && /* @__PURE__ */ React__default.createElement(StatusError, null, "Failed")),
3112
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, "Start time: ", (_e = (_d = job.status) == null ? void 0 : _d.startTime) == null ? void 0 : _e.toString()),
3113
- ((_f = job.status) == null ? void 0 : _f.completionTime) && /* @__PURE__ */ React__default.createElement(Grid, { item: true }, "Completion time: ", job.status.completionTime.toString())
3114
- )
3115
- );
3116
- };
3117
- const JobAccordion = ({ job, ownedPods }) => {
3118
- return /* @__PURE__ */ React__default.createElement(Accordion, { TransitionProps: { unmountOnExit: true }, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(JobSummary, { job })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(PodsTable, { pods: ownedPods })));
3119
- };
3120
- const JobsAccordions = ({ jobs }) => {
3121
- const groupedResponses = useContext(GroupedResponsesContext);
3122
- return /* @__PURE__ */ React__default.createElement(
3123
- Grid,
3124
- {
3125
- container: true,
3126
- direction: "column",
3127
- justifyContent: "flex-start",
3128
- alignItems: "flex-start"
3129
- },
3130
- jobs.map((job, i) => /* @__PURE__ */ React__default.createElement(Grid, { container: true, item: true, key: i, xs: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: true }, /* @__PURE__ */ React__default.createElement(
3131
- JobAccordion,
3132
- {
3133
- ownedPods: getOwnedResources(job, groupedResponses.pods),
3134
- job
3135
- }
3136
- ))))
3137
- );
3138
- };
3139
-
3140
- const CronJobDrawer = ({
3141
- cronJob,
3142
- expanded
3143
- }) => {
3144
- var _a, _b, _c;
3145
- const namespace = (_a = cronJob.metadata) == null ? void 0 : _a.namespace;
3146
- return /* @__PURE__ */ React__default.createElement(
3147
- KubernetesStructuredMetadataTableDrawer,
3148
- {
3149
- object: cronJob,
3150
- expanded,
3151
- kind: "CronJob",
3152
- renderObject: (cronJobObj) => {
3153
- var _a2, _b2, _c2, _d, _e, _f, _g, _h;
3154
- return {
3155
- schedule: (_b2 = (_a2 = cronJobObj.spec) == null ? void 0 : _a2.schedule) != null ? _b2 : "???",
3156
- startingDeadlineSeconds: (_d = (_c2 = cronJobObj.spec) == null ? void 0 : _c2.startingDeadlineSeconds) != null ? _d : "???",
3157
- concurrencyPolicy: (_f = (_e = cronJobObj.spec) == null ? void 0 : _e.concurrencyPolicy) != null ? _f : "???",
3158
- lastScheduleTime: (_h = (_g = cronJobObj.status) == null ? void 0 : _g.lastScheduleTime) != null ? _h : "???"
3159
- };
3160
- }
3161
- },
3162
- /* @__PURE__ */ React__default.createElement(
3163
- Grid,
3164
- {
3165
- container: true,
3166
- direction: "column",
3167
- justifyContent: "flex-start",
3168
- alignItems: "flex-start",
3169
- spacing: 0
3170
- },
3171
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, (_c = (_b = cronJob.metadata) == null ? void 0 : _b.name) != null ? _c : "unknown object")),
3172
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, "CronJob")),
3173
- namespace && /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Chip, { size: "small", label: `namespace: ${namespace}` }))
3174
- )
3175
- );
3176
- };
3177
-
3178
- const k8sCronAliases = /* @__PURE__ */ new Map([
3179
- ["@yearly", "0 0 1 1 *"],
3180
- ["@annually", "0 0 1 1 *"],
3181
- ["@monthly", "0 0 1 * *"],
3182
- ["@weekly", "0 0 * * 0"],
3183
- ["@daily", "0 0 * * *"],
3184
- ["@midnight", "0 0 * * *"],
3185
- ["@hourly", "0 * * * *"]
3186
- ]);
3187
- const humanizeCron = (schedule) => {
3188
- const deAliasedSchedule = k8sCronAliases.get(schedule) || schedule;
3189
- try {
3190
- return cronstrue.toString(deAliasedSchedule);
3191
- } catch (e) {
3192
- return deAliasedSchedule;
3193
- }
3194
- };
3195
-
3196
- const CronJobSummary = ({ cronJob }) => {
3197
- var _a, _b;
3198
- return /* @__PURE__ */ React__default.createElement(
3199
- Grid,
3200
- {
3201
- container: true,
3202
- direction: "row",
3203
- justifyContent: "space-between",
3204
- alignItems: "center",
3205
- spacing: 0
3206
- },
3207
- /* @__PURE__ */ React__default.createElement(Grid, { xs: 6, item: true }, /* @__PURE__ */ React__default.createElement(CronJobDrawer, { cronJob })),
3208
- /* @__PURE__ */ React__default.createElement(
3209
- Grid,
3210
- {
3211
- item: true,
3212
- container: true,
3213
- xs: 6,
3214
- direction: "column",
3215
- justifyContent: "flex-start",
3216
- alignItems: "flex-end",
3217
- spacing: 0
3218
- },
3219
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, ((_a = cronJob.spec) == null ? void 0 : _a.suspend) ? /* @__PURE__ */ React__default.createElement(StatusError, null, "Suspended") : /* @__PURE__ */ React__default.createElement(StatusOK, null, "Active")),
3220
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, "Schedule:", " ", ((_b = cronJob.spec) == null ? void 0 : _b.schedule) ? `${cronJob.spec.schedule} (${humanizeCron(
3221
- cronJob.spec.schedule
3222
- )})` : "N/A"))
3223
- )
3224
- );
3225
- };
3226
- const CronJobAccordion = ({ cronJob, ownedJobs }) => {
3227
- return /* @__PURE__ */ React__default.createElement(Accordion, { TransitionProps: { unmountOnExit: true }, variant: "outlined" }, /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(CronJobSummary, { cronJob })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(JobsAccordions, { jobs: ownedJobs.reverse() })));
3228
- };
3229
- const CronJobsAccordions = ({}) => {
3230
- const groupedResponses = useContext(GroupedResponsesContext);
3231
- return /* @__PURE__ */ React__default.createElement(
3232
- Grid,
3233
- {
3234
- container: true,
3235
- direction: "column",
3236
- justifyContent: "flex-start",
3237
- alignItems: "flex-start"
3238
- },
3239
- groupedResponses.cronJobs.map((cronJob, i) => /* @__PURE__ */ React__default.createElement(Grid, { container: true, item: true, key: i, xs: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: true }, /* @__PURE__ */ React__default.createElement(
3240
- CronJobAccordion,
3241
- {
3242
- ownedJobs: getOwnedResources(cronJob, groupedResponses.jobs),
3243
- cronJob
3244
- }
3245
- ))))
3246
- );
3247
- };
3248
-
3249
- const RolloutDrawer = ({
3250
- rollout,
3251
- expanded
3252
- }) => {
3253
- var _a, _b;
3254
- return /* @__PURE__ */ React__default.createElement(
3255
- KubernetesStructuredMetadataTableDrawer,
3256
- {
3257
- object: rollout,
3258
- expanded,
3259
- kind: "Rollout",
3260
- renderObject: () => ({})
3261
- },
3262
- /* @__PURE__ */ React__default.createElement(
3263
- Grid,
3264
- {
3265
- container: true,
3266
- direction: "column",
3267
- justifyContent: "flex-start",
3268
- alignItems: "flex-start",
3269
- spacing: 0
3270
- },
3271
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, (_b = (_a = rollout.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown object")),
3272
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, "Rollout"))
3273
- )
3274
- );
3275
- };
3276
-
3277
- const isSetWeightStep = (step) => step.hasOwnProperty("setWeight");
3278
- const isPauseStep = (step) => step.hasOwnProperty("pause");
3279
- const isAnalysisStep = (step) => step.hasOwnProperty("analysis");
3280
- const createLabelForStep = (step) => {
3281
- if (isSetWeightStep(step)) {
3282
- return `setWeight ${step.setWeight}%`;
3283
- } else if (isPauseStep(step)) {
3284
- return step.pause.duration === void 0 ? "infinite pause" : `pause for ${step.pause.duration}`;
3285
- } else if (isAnalysisStep(step)) {
3286
- return /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement(Typography$1, { paragraph: true }, "analysis templates:"), step.analysis.templates.map((t, i) => /* @__PURE__ */ React__default.createElement(Typography$1, { paragraph: true, key: i }, `${t.templateName}${t.clusterScope ? " (cluster scoped)" : ""}`)));
3287
- }
3288
- return "unknown step";
3289
- };
3290
- const StepsProgress = ({
3291
- currentStepIndex,
3292
- aborted,
3293
- steps
3294
- }) => {
3295
- const activeStepIndex = currentStepIndex >= steps.length ? currentStepIndex + 1 : currentStepIndex;
3296
- return /* @__PURE__ */ React__default.createElement(Stepper, { activeStep: aborted ? -1 : activeStepIndex, alternativeLabel: true }, steps.map((step, i) => /* @__PURE__ */ React__default.createElement(Step, { key: i }, /* @__PURE__ */ React__default.createElement(StepLabel, { "data-testid": `step-${i}` }, createLabelForStep(step)))).concat(
3297
- /* @__PURE__ */ React__default.createElement(Step, { key: "-1" }, /* @__PURE__ */ React__default.createElement(StepLabel, { "data-testid": "step--1" }, "Canary promoted"))
3298
- ));
3299
- };
3300
-
3301
- const AbortedTitle = /* @__PURE__ */ React__default.createElement(
3302
- "div",
3303
- {
3304
- style: {
3305
- display: "flex",
3306
- alignItems: "center",
3307
- flexWrap: "wrap"
3308
- }
3309
- },
3310
- /* @__PURE__ */ React__default.createElement(ErrorOutlineIcon, null),
3311
- /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle1" }, "Aborted")
3312
- );
3313
- const findAbortedMessage = (rollout) => {
3314
- var _a, _b, _c;
3315
- return (_c = (_b = (_a = rollout.status) == null ? void 0 : _a.conditions) == null ? void 0 : _b.find(
3316
- (c) => c.type === "Progressing" && c.status === "False" && c.reason === "RolloutAborted"
3317
- )) == null ? void 0 : _c.message;
3318
- };
3319
- const RolloutSummary = ({
3320
- rollout,
3321
- numberOfCurrentPods,
3322
- numberOfPodsWithErrors,
3323
- hpa
3324
- }) => {
3325
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3326
- const pauseTime = (_c = (_b = (_a = rollout.status) == null ? void 0 : _a.pauseConditions) == null ? void 0 : _b.find(
3327
- (p) => p.reason === "CanaryPauseStep"
3328
- )) == null ? void 0 : _c.startTime;
3329
- const abortedMessage = findAbortedMessage(rollout);
3330
- return /* @__PURE__ */ React__default.createElement(
3331
- Grid,
3332
- {
3333
- container: true,
3334
- direction: "row",
3335
- justifyContent: "space-between",
3336
- alignItems: "center",
3337
- spacing: 0
3338
- },
3339
- /* @__PURE__ */ React__default.createElement(Grid, { xs: 6, item: true }, /* @__PURE__ */ React__default.createElement(RolloutDrawer, { rollout })),
3340
- hpa && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 3 }, /* @__PURE__ */ React__default.createElement(HorizontalPodAutoscalerDrawer, { hpa }, /* @__PURE__ */ React__default.createElement(
3341
- Grid,
3342
- {
3343
- item: true,
3344
- container: true,
3345
- direction: "column",
3346
- justifyContent: "flex-start",
3347
- alignItems: "flex-start",
3348
- spacing: 0
3349
- },
3350
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "min replicas ", (_e = (_d = hpa.spec) == null ? void 0 : _d.minReplicas) != null ? _e : "?", " / max replicas", " ", (_g = (_f = hpa.spec) == null ? void 0 : _f.maxReplicas) != null ? _g : "?")),
3351
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "current CPU usage:", " ", (_i = (_h = hpa.status) == null ? void 0 : _h.currentCPUUtilizationPercentage) != null ? _i : "?", "%")),
3352
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, "target CPU usage:", " ", (_k = (_j = hpa.spec) == null ? void 0 : _j.targetCPUUtilizationPercentage) != null ? _k : "?", "%"))
3353
- ))),
3354
- /* @__PURE__ */ React__default.createElement(
3355
- Grid,
3356
- {
3357
- item: true,
3358
- container: true,
3359
- xs: 3,
3360
- direction: "column",
3361
- justifyContent: "flex-start",
3362
- alignItems: "flex-end",
3363
- spacing: 0
3364
- },
3365
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(StatusOK, null, numberOfCurrentPods, " pods")),
3366
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, numberOfPodsWithErrors > 0 ? /* @__PURE__ */ React__default.createElement(StatusError, null, numberOfPodsWithErrors, " pod", numberOfPodsWithErrors > 1 ? "s" : "", " with errors") : /* @__PURE__ */ React__default.createElement(StatusOK, null, "No pods with errors"))
3367
- ),
3368
- pauseTime && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 3 }, /* @__PURE__ */ React__default.createElement(
3369
- "div",
3370
- {
3371
- style: {
3372
- display: "flex",
3373
- alignItems: "center",
3374
- flexWrap: "wrap"
3375
- }
3376
- },
3377
- /* @__PURE__ */ React__default.createElement(PauseIcon, null),
3378
- /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle1" }, "Paused (", DateTime.fromISO(pauseTime).toRelative({ locale: "en" }), ")")
3379
- )),
3380
- abortedMessage && /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 3 }, AbortedTitle)
3381
- );
3382
- };
3383
- const RolloutAccordion = ({
3384
- rollout,
3385
- ownedPods,
3386
- matchingHpa,
3387
- defaultExpanded
3388
- }) => {
3389
- var _a, _b, _c, _d, _e, _f;
3390
- const podNamesWithErrors = useContext(PodNamesWithErrorsContext);
3391
- const podsWithErrors = ownedPods.filter(
3392
- (p) => {
3393
- var _a2, _b2;
3394
- return podNamesWithErrors.has((_b2 = (_a2 = p.metadata) == null ? void 0 : _a2.name) != null ? _b2 : "");
3395
- }
3396
- );
3397
- const currentStepIndex = (_b = (_a = rollout.status) == null ? void 0 : _a.currentStepIndex) != null ? _b : 0;
3398
- const abortedMessage = findAbortedMessage(rollout);
3399
- return /* @__PURE__ */ React__default.createElement(
3400
- Accordion,
3401
- {
3402
- defaultExpanded,
3403
- TransitionProps: { unmountOnExit: true },
3404
- variant: "outlined"
3405
- },
3406
- /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(
3407
- RolloutSummary,
3408
- {
3409
- rollout,
3410
- numberOfCurrentPods: ownedPods.length,
3411
- numberOfPodsWithErrors: podsWithErrors.length,
3412
- hpa: matchingHpa
3413
- }
3414
- )),
3415
- /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement("div", { style: { width: "100%" } }, /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h6" }, "Rollout status")), /* @__PURE__ */ React__default.createElement("div", { style: { margin: "1rem" } }, abortedMessage && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, AbortedTitle, /* @__PURE__ */ React__default.createElement(Typography, { variant: "subtitle2" }, abortedMessage)), /* @__PURE__ */ React__default.createElement(
3416
- StepsProgress,
3417
- {
3418
- aborted: abortedMessage !== void 0,
3419
- steps: (_f = (_e = (_d = (_c = rollout.spec) == null ? void 0 : _c.strategy) == null ? void 0 : _d.canary) == null ? void 0 : _e.steps) != null ? _f : [],
3420
- currentStepIndex
3421
- }
3422
- )), /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement(
3423
- PodsTable,
3424
- {
3425
- pods: ownedPods,
3426
- extraColumns: [READY_COLUMNS, RESOURCE_COLUMNS]
3427
- }
3428
- ))))
3429
- );
3430
- };
3431
- const RolloutAccordions = ({
3432
- rollouts,
3433
- defaultExpanded = false
3434
- }) => {
3435
- const groupedResponses = useContext(GroupedResponsesContext);
3436
- return /* @__PURE__ */ React__default.createElement(
3437
- Grid,
3438
- {
3439
- container: true,
3440
- direction: "column",
3441
- justifyContent: "flex-start",
3442
- alignItems: "flex-start"
3443
- },
3444
- rollouts.map((rollout, i) => {
3445
- var _a, _b;
3446
- return /* @__PURE__ */ React__default.createElement(Grid, { container: true, item: true, key: i, xs: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: true }, /* @__PURE__ */ React__default.createElement(
3447
- RolloutAccordion,
3448
- {
3449
- defaultExpanded,
3450
- matchingHpa: getMatchingHpa(
3451
- {
3452
- name: (_a = rollout.metadata) == null ? void 0 : _a.name,
3453
- namespace: (_b = rollout.metadata) == null ? void 0 : _b.namespace,
3454
- kind: "rollout"
3455
- },
3456
- groupedResponses.horizontalPodAutoscalers
3457
- ),
3458
- ownedPods: getOwnedPodsThroughReplicaSets(
3459
- rollout,
3460
- groupedResponses.replicaSets,
3461
- groupedResponses.pods
3462
- ),
3463
- rollout
3464
- }
3465
- )));
3466
- })
3467
- );
3468
- };
3469
-
3470
- const capitalize = (str) => str.charAt(0).toLocaleUpperCase("en-US") + str.slice(1);
3471
- const DefaultCustomResourceDrawer = ({
3472
- customResource,
3473
- customResourceName,
3474
- expanded
3475
- }) => {
3476
- var _a, _b;
3477
- const capitalizedName = capitalize(customResourceName);
3478
- return /* @__PURE__ */ React__default.createElement(
3479
- KubernetesStructuredMetadataTableDrawer,
3480
- {
3481
- object: customResource,
3482
- expanded,
3483
- kind: capitalizedName,
3484
- renderObject: (cr) => cr
3485
- },
3486
- /* @__PURE__ */ React__default.createElement(
3487
- Grid,
3488
- {
3489
- container: true,
3490
- direction: "column",
3491
- justifyContent: "flex-start",
3492
- alignItems: "flex-start",
3493
- spacing: 0
3494
- },
3495
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, (_b = (_a = customResource.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown object")),
3496
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, capitalizedName))
3497
- )
3498
- );
3499
- };
3500
-
3501
- const DefaultCustomResourceSummary = ({
3502
- customResource,
3503
- customResourceName
3504
- }) => {
3505
- return /* @__PURE__ */ React__default.createElement(
3506
- Grid,
3507
- {
3508
- container: true,
3509
- direction: "row",
3510
- justifyContent: "space-between",
3511
- alignItems: "center",
3512
- spacing: 0
3513
- },
3514
- /* @__PURE__ */ React__default.createElement(Grid, { xs: 12, item: true }, /* @__PURE__ */ React__default.createElement(
3515
- DefaultCustomResourceDrawer,
3516
- {
3517
- customResource,
3518
- customResourceName
3519
- }
3520
- ))
3521
- );
3522
- };
3523
- const DefaultCustomResourceAccordion = ({
3524
- customResource,
3525
- customResourceName,
3526
- defaultExpanded
3527
- }) => {
3528
- return /* @__PURE__ */ React__default.createElement(
3529
- Accordion,
3530
- {
3531
- defaultExpanded,
3532
- TransitionProps: { unmountOnExit: true },
3533
- variant: "outlined"
3534
- },
3535
- /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(
3536
- DefaultCustomResourceSummary,
3537
- {
3538
- customResource,
3539
- customResourceName
3540
- }
3541
- )),
3542
- /* @__PURE__ */ React__default.createElement(AccordionDetails, null, customResource.hasOwnProperty("status") && /* @__PURE__ */ React__default.createElement(StructuredMetadataTable, { metadata: customResource.status }))
3543
- );
3544
- };
3545
- const DefaultCustomResourceAccordions = ({
3546
- customResources,
3547
- customResourceName,
3548
- defaultExpanded = false
3549
- }) => {
3550
- return /* @__PURE__ */ React__default.createElement(
3551
- Grid,
3552
- {
3553
- container: true,
3554
- direction: "column",
3555
- justifyContent: "flex-start",
3556
- alignItems: "flex-start"
3557
- },
3558
- customResources.map((cr, i) => /* @__PURE__ */ React__default.createElement(Grid, { container: true, item: true, key: i, xs: true }, /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: true }, /* @__PURE__ */ React__default.createElement(
3559
- DefaultCustomResourceAccordion,
3560
- {
3561
- defaultExpanded,
3562
- customResource: cr,
3563
- customResourceName
3564
- }
3565
- ))))
3566
- );
3567
- };
3568
-
3569
- const kindToResource = (customResources) => {
3570
- return lodash.groupBy(customResources, (value) => {
3571
- return value.kind;
3572
- });
3573
- };
3574
- const CustomResources = ({}) => {
3575
- const groupedResponses = useContext(GroupedResponsesContext);
3576
- const kindToResourceMap = kindToResource(groupedResponses.customResources);
3577
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, Object.entries(kindToResourceMap).map(([kind, resources], i) => {
3578
- switch (kind) {
3579
- case "Rollout":
3580
- return /* @__PURE__ */ React__default.createElement(RolloutAccordions, { key: i, rollouts: resources });
3581
- default:
3582
- return /* @__PURE__ */ React__default.createElement(
3583
- DefaultCustomResourceAccordions,
3584
- {
3585
- key: i,
3586
- customResources: resources,
3587
- customResourceName: kind
3588
- }
3589
- );
3590
- }
3591
- }));
3592
- };
3593
-
3594
- const ClusterSummary = ({
3595
- clusterName,
3596
- totalNumberOfPods,
3597
- numberOfPodsWithErrors
3598
- }) => {
3599
- return /* @__PURE__ */ React__default.createElement(
3600
- Grid,
3601
- {
3602
- container: true,
3603
- direction: "row",
3604
- justifyContent: "space-between",
3605
- alignItems: "flex-start",
3606
- spacing: 0
3607
- },
3608
- /* @__PURE__ */ React__default.createElement(
3609
- Grid,
3610
- {
3611
- xs: 6,
3612
- item: true,
3613
- container: true,
3614
- direction: "column",
3615
- justifyContent: "flex-start",
3616
- alignItems: "flex-start",
3617
- spacing: 0
3618
- },
3619
- /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "body1" }, clusterName), /* @__PURE__ */ React__default.createElement(Typography, { color: "textSecondary", variant: "subtitle1" }, "Cluster"))
3620
- ),
3621
- /* @__PURE__ */ React__default.createElement(
3622
- Grid,
3623
- {
3624
- item: true,
3625
- container: true,
3626
- xs: 3,
3627
- direction: "column",
3628
- justifyContent: "flex-start",
3629
- alignItems: "flex-end",
3630
- spacing: 0
3631
- },
3632
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(StatusOK, null, totalNumberOfPods, " pods")),
3633
- /* @__PURE__ */ React__default.createElement(Grid, { item: true }, numberOfPodsWithErrors > 0 ? /* @__PURE__ */ React__default.createElement(StatusError, null, numberOfPodsWithErrors, " pods with errors") : /* @__PURE__ */ React__default.createElement(StatusOK, null, "No pods with errors"))
3634
- )
3635
- );
3636
- };
3637
- const Cluster = ({ clusterObjects, podsWithErrors }) => {
3638
- const groupedResponses = groupResponses(clusterObjects.resources);
3639
- const podMetricsMap = /* @__PURE__ */ new Map();
3640
- podMetricsMap.set(clusterObjects.cluster.name, clusterObjects.podMetrics);
3641
- return /* @__PURE__ */ React__default.createElement(ClusterContext.Provider, { value: clusterObjects.cluster }, /* @__PURE__ */ React__default.createElement(GroupedResponsesContext.Provider, { value: groupedResponses }, /* @__PURE__ */ React__default.createElement(PodMetricsContext.Provider, { value: podMetricsMap }, /* @__PURE__ */ React__default.createElement(PodNamesWithErrorsContext.Provider, { value: podsWithErrors }, /* @__PURE__ */ React__default.createElement(Accordion, { TransitionProps: { unmountOnExit: true } }, /* @__PURE__ */ React__default.createElement(AccordionSummary, { expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null) }, /* @__PURE__ */ React__default.createElement(
3642
- ClusterSummary,
3643
- {
3644
- clusterName: clusterObjects.cluster.name,
3645
- totalNumberOfPods: groupedResponses.pods.length,
3646
- numberOfPodsWithErrors: podsWithErrors.size
3647
- }
3648
- )), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(Grid, { container: true, direction: "column" }, groupedResponses.customResources.length > 0 ? /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(CustomResources, null)) : void 0, groupedResponses.deployments.length > 0 ? /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(DeploymentsAccordions, null)) : void 0, groupedResponses.statefulsets.length > 0 ? /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(StatefulSetsAccordions, null)) : void 0, groupedResponses.ingresses.length > 0 ? /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(IngressesAccordions, null)) : void 0, groupedResponses.services.length > 0 ? /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(ServicesAccordions, null)) : void 0, groupedResponses.cronJobs.length > 0 ? /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(CronJobsAccordions, null)) : void 0)))))));
3649
- };
3650
-
3651
- const KubernetesContent = ({
3652
- entity,
3653
- refreshIntervalMs
3654
- }) => {
3655
- var _a;
3656
- const { kubernetesObjects, error } = useKubernetesObjects(
3657
- entity,
3658
- refreshIntervalMs
3659
- );
3660
- const clustersWithErrors = (_a = kubernetesObjects == null ? void 0 : kubernetesObjects.items.filter((r) => r.errors.length > 0)) != null ? _a : [];
3661
- const detectedErrors = kubernetesObjects !== void 0 ? detectErrors(kubernetesObjects) : /* @__PURE__ */ new Map();
3662
- return /* @__PURE__ */ React__default.createElement(DetectedErrorsContext.Provider, { value: [...detectedErrors.values()].flat() }, /* @__PURE__ */ React__default.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React__default.createElement(Content, null, kubernetesObjects === void 0 && error === void 0 && /* @__PURE__ */ React__default.createElement(Progress, null), clustersWithErrors.length > 0 && /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(
3663
- ErrorPanel,
3664
- {
3665
- entityName: entity.metadata.name,
3666
- clustersWithErrors
3667
- }
3668
- ))), error !== void 0 && /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(
3669
- ErrorPanel,
3670
- {
3671
- entityName: entity.metadata.name,
3672
- errorMessage: error
3673
- }
3674
- ))), kubernetesObjects && /* @__PURE__ */ React__default.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(ErrorReporting, { detectedErrors })), /* @__PURE__ */ React__default.createElement(Grid, { item: true }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h3" }, "Your Clusters")), /* @__PURE__ */ React__default.createElement(Grid, { item: true, container: true }, (kubernetesObjects == null ? void 0 : kubernetesObjects.items.length) <= 0 && /* @__PURE__ */ React__default.createElement(
3675
- Grid,
3676
- {
3677
- container: true,
3678
- justifyContent: "space-around",
3679
- direction: "row",
3680
- alignItems: "center",
3681
- spacing: 2
3682
- },
3683
- /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 4 }, /* @__PURE__ */ React__default.createElement(Typography, { variant: "h5" }, "No resources on any known clusters for", " ", entity.metadata.name)),
3684
- /* @__PURE__ */ React__default.createElement(Grid, { item: true, xs: 4 }, /* @__PURE__ */ React__default.createElement(
3685
- "img",
3686
- {
3687
- src: EmptyStateImage,
3688
- alt: "EmptyState",
3689
- "data-testid": "emptyStateImg"
118
+ title: "No Kubernetes resources",
119
+ description: `No resources on any known clusters for ${entity.metadata.name}`
3690
120
  }
3691
121
  ))
3692
122
  ), (kubernetesObjects == null ? void 0 : kubernetesObjects.items.length) > 0 && (kubernetesObjects == null ? void 0 : kubernetesObjects.items.map((item, i) => {
@@ -3694,7 +124,7 @@ const KubernetesContent = ({
3694
124
  const podsWithErrors = new Set(
3695
125
  (_a2 = detectedErrors.get(item.cluster.name)) == null ? void 0 : _a2.filter((de) => de.sourceRef.kind === "Pod").map((de) => de.sourceRef.name)
3696
126
  );
3697
- return /* @__PURE__ */ React__default.createElement(Grid, { item: true, key: i, xs: 12 }, /* @__PURE__ */ React__default.createElement(
127
+ return /* @__PURE__ */ React.createElement(Grid, { item: true, key: i, xs: 12 }, /* @__PURE__ */ React.createElement(
3698
128
  Cluster,
3699
129
  {
3700
130
  clusterObjects: item,
@@ -3718,11 +148,11 @@ const Router = (props) => {
3718
148
  const kubernetesAnnotationValue = (_a = entity.metadata.annotations) == null ? void 0 : _a[KUBERNETES_ANNOTATION];
3719
149
  const kubernetesLabelSelectorQueryAnnotationValue = (_b = entity.metadata.annotations) == null ? void 0 : _b[KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION];
3720
150
  if (kubernetesAnnotationValue || kubernetesLabelSelectorQueryAnnotationValue) {
3721
- return /* @__PURE__ */ React__default.createElement(Routes, null, /* @__PURE__ */ React__default.createElement(
151
+ return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(
3722
152
  Route,
3723
153
  {
3724
154
  path: "/",
3725
- element: /* @__PURE__ */ React__default.createElement(
155
+ element: /* @__PURE__ */ React.createElement(
3726
156
  KubernetesContent,
3727
157
  {
3728
158
  entity,
@@ -3732,7 +162,7 @@ const Router = (props) => {
3732
162
  }
3733
163
  ));
3734
164
  }
3735
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(MissingAnnotationEmptyState, { annotation: KUBERNETES_ANNOTATION }), /* @__PURE__ */ React__default.createElement("h1", null, "Or use a label selector query, which takes precedence over the previous annotation."), /* @__PURE__ */ React__default.createElement(
165
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(MissingAnnotationEmptyState, { annotation: KUBERNETES_ANNOTATION }), /* @__PURE__ */ React.createElement("h1", null, "Or use a label selector query, which takes precedence over the previous annotation."), /* @__PURE__ */ React.createElement(
3736
166
  Button,
3737
167
  {
3738
168
  variant: "contained",
@@ -3749,5 +179,5 @@ var Router$1 = /*#__PURE__*/Object.freeze({
3749
179
  Router: Router
3750
180
  });
3751
181
 
3752
- export { Cluster, ClusterContext, ContainerCard, CronJobsAccordions, CustomResources, DetectedErrorsContext, EntityKubernetesContent, ErrorList, ErrorPanel, ErrorReporting, Events, EventsContent, FixDialog, GoogleKubernetesAuthProvider, GroupedResponsesContext, HorizontalPodAutoscalerDrawer, IngressesAccordions, JobsAccordions, KubernetesAuthProviders, KubernetesBackendClient, KubernetesContent, KubernetesDrawer, KubernetesDrawerContent, KubernetesProxyClient, KubernetesStructuredMetadataTableDrawer, LinkErrorPanel, PendingPodContent, PodDrawer, PodExecTerminal, PodExecTerminalDialog, PodLogs, PodLogsDialog, PodMetricsContext, PodNamesWithErrorsContext, PodNamesWithMetricsContext, PodsTable, ResourceUtilization, Router, ServerSideKubernetesAuthProvider, ServicesAccordions, clusterLinksFormatters, detectErrors, formatClusterLink, isKubernetesAvailable, kubernetesApiRef, kubernetesAuthProvidersApiRef, kubernetesPlugin, kubernetesProxyApiRef, kubernetesPlugin as plugin, useCustomResources, useEvents, useIsPodExecTerminalSupported, useKubernetesObjects, useMatchingErrors, usePodLogs, usePodMetrics };
182
+ export { EntityKubernetesContent, Router, isKubernetesAvailable, kubernetesPlugin, kubernetesPlugin as plugin };
3753
183
  //# sourceMappingURL=index.esm.js.map