@backstage/plugin-kubernetes 0.6.5-next.2 → 0.6.6-next.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # @backstage/plugin-kubernetes
2
2
 
3
+ ## 0.6.6-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 4328737af6: Add support to fetch data for Stateful Sets and display an accordion in the same way as with Deployments
8
+ - 81304e3e91: Fix for HPA matching when deploying same HPA in multiple namespaces
9
+ - Updated dependencies
10
+ - @backstage/plugin-catalog-react@1.1.1-next.0
11
+ - @backstage/core-components@0.9.5-next.0
12
+ - @backstage/plugin-kubernetes-common@0.3.0-next.0
13
+
14
+ ## 0.6.5
15
+
16
+ ### Patch Changes
17
+
18
+ - 1ef98cfe48: add Azure Identity auth provider and AKS dashboard formatter
19
+ - 447e060872: Add support for 'oidc' as authProvider for kubernetes authentication
20
+ and adds optional 'oidcTokenProvider' config value. This will allow
21
+ users to authenticate to kubernetes cluster using id tokens obtained
22
+ from the configured auth provider in their backstage instance.
23
+ - Updated dependencies
24
+ - @backstage/core-components@0.9.4
25
+ - @backstage/plugin-kubernetes-common@0.2.10
26
+ - @backstage/core-plugin-api@1.0.2
27
+ - @backstage/plugin-catalog-react@1.1.0
28
+ - @backstage/config@1.0.1
29
+ - @backstage/catalog-model@1.0.2
30
+
31
+ ## 0.6.5-next.3
32
+
33
+ ### Patch Changes
34
+
35
+ - 447e060872: Add support for 'oidc' as authProvider for kubernetes authentication
36
+ and adds optional 'oidcTokenProvider' config value. This will allow
37
+ users to authenticate to kubernetes cluster using id tokens obtained
38
+ from the configured auth provider in their backstage instance.
39
+ - Updated dependencies
40
+ - @backstage/plugin-kubernetes-common@0.2.10-next.1
41
+ - @backstage/core-components@0.9.4-next.2
42
+
3
43
  ## 0.6.5-next.2
4
44
 
5
45
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  /// <reference types="react" />
2
2
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
3
- import { DiscoveryApi, IdentityApi, OAuthApi } from '@backstage/core-plugin-api';
3
+ import { DiscoveryApi, IdentityApi, OAuthApi, OpenIdConnectApi } from '@backstage/core-plugin-api';
4
4
  import { Entity } from '@backstage/catalog-model';
5
5
  import { KubernetesRequestBody, ObjectsByEntityResponse, ClusterObjects, ClientPodStatus, ClusterAttributes } from '@backstage/plugin-kubernetes-common';
6
6
  import { JsonObject } from '@backstage/types';
7
- import { V1Pod, V1ReplicaSet, V1Deployment, V1HorizontalPodAutoscaler, V1Service, V1ConfigMap, V1Ingress, V1Job, V1CronJob, V1ObjectMeta } from '@kubernetes/client-node';
7
+ import { V1Pod, V1ReplicaSet, V1Deployment, V1HorizontalPodAutoscaler, V1Service, V1ConfigMap, V1Ingress, V1Job, V1CronJob, V1StatefulSet, V1ObjectMeta } from '@kubernetes/client-node';
8
8
  import React from 'react';
9
9
 
10
10
  declare const kubernetesPlugin: _backstage_core_plugin_api.BackstagePlugin<{
@@ -22,6 +22,7 @@ interface KubernetesApi {
22
22
  getClusters(): Promise<{
23
23
  name: string;
24
24
  authProvider: string;
25
+ oidcTokenProvider?: string | undefined;
25
26
  }[]>;
26
27
  }
27
28
 
@@ -53,6 +54,9 @@ declare class KubernetesAuthProviders implements KubernetesAuthProvidersApi {
53
54
  private readonly kubernetesAuthProviderMap;
54
55
  constructor(options: {
55
56
  googleAuthApi: OAuthApi;
57
+ oidcProviders?: {
58
+ [key: string]: OpenIdConnectApi;
59
+ };
56
60
  });
57
61
  decorateRequestBodyForAuth(authProvider: string, requestBody: KubernetesRequestBody): Promise<KubernetesRequestBody>;
58
62
  }
@@ -97,6 +101,7 @@ interface GroupedResponses extends DeploymentResources {
97
101
  jobs: V1Job[];
98
102
  cronJobs: V1CronJob[];
99
103
  customResources: any[];
104
+ statefulsets: V1StatefulSet[];
100
105
  }
101
106
  interface ClusterLinksFormatterOptions {
102
107
  dashboardUrl?: URL;
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createApiRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef, identityApiRef, googleAuthApiRef, createRoutableExtension, useApi } from '@backstage/core-plugin-api';
1
+ import { createApiRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef, identityApiRef, googleAuthApiRef, microsoftAuthApiRef, oktaAuthApiRef, oneloginAuthApiRef, createRoutableExtension, useApi } from '@backstage/core-plugin-api';
2
2
  import * as React from 'react';
3
3
  import React__default, { Fragment, useState, useEffect, useContext } from 'react';
4
4
  import { useEntity } from '@backstage/plugin-catalog-react';
@@ -114,6 +114,24 @@ class AzureKubernetesAuthProvider {
114
114
  }
115
115
  }
116
116
 
117
+ class OidcKubernetesAuthProvider {
118
+ constructor(providerName, authProvider) {
119
+ this.providerName = providerName;
120
+ this.authProvider = authProvider;
121
+ }
122
+ async decorateRequestBodyForAuth(requestBody) {
123
+ const authToken = await this.authProvider.getIdToken();
124
+ const auth = { ...requestBody.auth };
125
+ if (auth.oidc) {
126
+ auth.oidc[this.providerName] = authToken;
127
+ } else {
128
+ auth.oidc = { [this.providerName]: authToken };
129
+ }
130
+ requestBody.auth = auth;
131
+ return requestBody;
132
+ }
133
+ }
134
+
117
135
  class KubernetesAuthProviders {
118
136
  constructor(options) {
119
137
  this.kubernetesAuthProviderMap = /* @__PURE__ */ new Map();
@@ -122,12 +140,20 @@ class KubernetesAuthProviders {
122
140
  this.kubernetesAuthProviderMap.set("googleServiceAccount", new GoogleServiceAccountAuthProvider());
123
141
  this.kubernetesAuthProviderMap.set("aws", new AwsKubernetesAuthProvider());
124
142
  this.kubernetesAuthProviderMap.set("azure", new AzureKubernetesAuthProvider());
143
+ if (options.oidcProviders) {
144
+ Object.keys(options.oidcProviders).forEach((provider) => {
145
+ this.kubernetesAuthProviderMap.set(`oidc.${provider}`, new OidcKubernetesAuthProvider(provider, options.oidcProviders[provider]));
146
+ });
147
+ }
125
148
  }
126
149
  async decorateRequestBodyForAuth(authProvider, requestBody) {
127
150
  const kubernetesAuthProvider = this.kubernetesAuthProviderMap.get(authProvider);
128
151
  if (kubernetesAuthProvider) {
129
152
  return await kubernetesAuthProvider.decorateRequestBodyForAuth(requestBody);
130
153
  }
154
+ if (authProvider.startsWith("oidc.")) {
155
+ throw new Error(`KubernetesAuthProviders has no oidcProvider configured for ${authProvider}`);
156
+ }
131
157
  throw new Error(`authProvider "${authProvider}" has no KubernetesAuthProvider defined for it`);
132
158
  }
133
159
  }
@@ -148,9 +174,25 @@ const kubernetesPlugin = createPlugin({
148
174
  }),
149
175
  createApiFactory({
150
176
  api: kubernetesAuthProvidersApiRef,
151
- deps: { googleAuthApi: googleAuthApiRef },
152
- factory: ({ googleAuthApi }) => {
153
- return new KubernetesAuthProviders({ googleAuthApi });
177
+ deps: {
178
+ googleAuthApi: googleAuthApiRef,
179
+ microsoftAuthApi: microsoftAuthApiRef,
180
+ oktaAuthApi: oktaAuthApiRef,
181
+ oneloginAuthApi: oneloginAuthApiRef
182
+ },
183
+ factory: ({
184
+ googleAuthApi,
185
+ microsoftAuthApi,
186
+ oktaAuthApi,
187
+ oneloginAuthApi
188
+ }) => {
189
+ const oidcProviders = {
190
+ google: googleAuthApi,
191
+ microsoft: microsoftAuthApi,
192
+ okta: oktaAuthApi,
193
+ onelogin: oneloginAuthApi
194
+ };
195
+ return new KubernetesAuthProviders({ googleAuthApi, oidcProviders });
154
196
  }
155
197
  })
156
198
  ],
@@ -298,6 +340,9 @@ const groupResponses = (fetchResponse) => {
298
340
  case "customresources":
299
341
  prev.customResources.push(...next.resources);
300
342
  break;
343
+ case "statefulsets":
344
+ prev.statefulsets.push(...next.resources);
345
+ break;
301
346
  }
302
347
  return prev;
303
348
  }, {
@@ -310,7 +355,8 @@ const groupResponses = (fetchResponse) => {
310
355
  ingresses: [],
311
356
  jobs: [],
312
357
  cronJobs: [],
313
- customResources: []
358
+ customResources: [],
359
+ statefulsets: []
314
360
  });
315
361
  };
316
362
 
@@ -589,7 +635,7 @@ const useKubernetesObjects = (entity, intervalMs = 1e4) => {
589
635
  return;
590
636
  }
591
637
  const authProviders = [
592
- ...new Set(clusters.map((c) => c.authProvider))
638
+ ...new Set(clusters.map((c) => `${c.authProvider}${c.oidcTokenProvider ? `.${c.oidcTokenProvider}` : ""}`))
593
639
  ];
594
640
  let requestBody = {
595
641
  entity
@@ -635,7 +681,8 @@ const GroupedResponsesContext = React__default.createContext({
635
681
  ingresses: [],
636
682
  jobs: [],
637
683
  cronJobs: [],
638
- customResources: []
684
+ customResources: [],
685
+ statefulsets: []
639
686
  });
640
687
 
641
688
  const ClusterContext = React__default.createContext({
@@ -647,7 +694,8 @@ const kindMappings$3 = {
647
694
  pod: "pod",
648
695
  ingress: "ingress",
649
696
  service: "service",
650
- horizontalpodautoscaler: "deployment"
697
+ horizontalpodautoscaler: "deployment",
698
+ statefulset: "statefulset"
651
699
  };
652
700
  function standardFormatter(options) {
653
701
  var _a, _b, _c, _d;
@@ -1199,10 +1247,10 @@ const getOwnedPodsThroughReplicaSets = (potentialOwner, replicaSets, pods) => {
1199
1247
  return accum.concat(getOwnedResources(rs, pods));
1200
1248
  }, []);
1201
1249
  };
1202
- const getMatchingHpa = (ownerName, ownerKind, hpas) => {
1250
+ const getMatchingHpa = (owner, hpas) => {
1203
1251
  return hpas.find((hpa) => {
1204
- var _a, _b, _c, _d, _e, _f;
1205
- return ((_c = (_b = (_a = hpa.spec) == null ? void 0 : _a.scaleTargetRef) == null ? void 0 : _b.kind) != null ? _c : "").toLocaleLowerCase("en-US") === ownerKind.toLocaleLowerCase("en-US") && ((_f = (_e = (_d = hpa.spec) == null ? void 0 : _d.scaleTargetRef) == null ? void 0 : _e.name) != null ? _f : "") === (ownerName != null ? ownerName : "unknown-deployment");
1252
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1253
+ 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");
1206
1254
  });
1207
1255
  };
1208
1256
 
@@ -1298,7 +1346,7 @@ const DeploymentsAccordions = ({}) => {
1298
1346
  justifyContent: "flex-start",
1299
1347
  alignItems: "flex-start"
1300
1348
  }, groupedResponses.deployments.map((deployment, i) => {
1301
- var _a;
1349
+ var _a, _b;
1302
1350
  return /* @__PURE__ */ React__default.createElement(Grid, {
1303
1351
  container: true,
1304
1352
  item: true,
@@ -1308,13 +1356,178 @@ const DeploymentsAccordions = ({}) => {
1308
1356
  item: true,
1309
1357
  xs: true
1310
1358
  }, /* @__PURE__ */ React__default.createElement(DeploymentAccordion, {
1311
- matchingHpa: getMatchingHpa((_a = deployment.metadata) == null ? void 0 : _a.name, "deployment", groupedResponses.horizontalPodAutoscalers),
1359
+ matchingHpa: getMatchingHpa({
1360
+ name: (_a = deployment.metadata) == null ? void 0 : _a.name,
1361
+ namespace: (_b = deployment.metadata) == null ? void 0 : _b.namespace,
1362
+ kind: "deployment"
1363
+ }, groupedResponses.horizontalPodAutoscalers),
1312
1364
  ownedPods: getOwnedPodsThroughReplicaSets(deployment, groupedResponses.replicaSets, groupedResponses.pods),
1313
1365
  deployment
1314
1366
  })));
1315
1367
  }));
1316
1368
  };
1317
1369
 
1370
+ const StatefulSetDrawer = ({
1371
+ statefulset,
1372
+ expanded
1373
+ }) => {
1374
+ var _a, _b, _c;
1375
+ const namespace = (_a = statefulset.metadata) == null ? void 0 : _a.namespace;
1376
+ return /* @__PURE__ */ React__default.createElement(KubernetesDrawer, {
1377
+ object: statefulset,
1378
+ expanded,
1379
+ kind: "StatefulSet",
1380
+ renderObject: (statefulsetObj) => {
1381
+ var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j, _k, _l;
1382
+ const conditions = ((_b2 = (_a2 = statefulsetObj.status) == null ? void 0 : _a2.conditions) != null ? _b2 : []).map(renderCondition).reduce((accum, next) => {
1383
+ accum[next[0]] = next[1];
1384
+ return accum;
1385
+ }, {});
1386
+ return {
1387
+ updateStrategy: (_d = (_c2 = statefulset.spec) == null ? void 0 : _c2.updateStrategy) != null ? _d : "???",
1388
+ podManagementPolicy: (_f = (_e = statefulset.spec) == null ? void 0 : _e.podManagementPolicy) != null ? _f : "???",
1389
+ serviceName: (_h = (_g = statefulset.spec) == null ? void 0 : _g.serviceName) != null ? _h : "???",
1390
+ selector: (_j = (_i = statefulset.spec) == null ? void 0 : _i.selector) != null ? _j : "???",
1391
+ revisionHistoryLimit: (_l = (_k = statefulset.spec) == null ? void 0 : _k.revisionHistoryLimit) != null ? _l : "???",
1392
+ ...conditions
1393
+ };
1394
+ }
1395
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1396
+ container: true,
1397
+ direction: "column",
1398
+ justifyContent: "flex-start",
1399
+ alignItems: "flex-start",
1400
+ spacing: 0
1401
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1402
+ item: true
1403
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1404
+ variant: "h5"
1405
+ }, (_c = (_b = statefulset.metadata) == null ? void 0 : _b.name) != null ? _c : "unknown object")), /* @__PURE__ */ React__default.createElement(Grid, {
1406
+ item: true
1407
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1408
+ color: "textSecondary",
1409
+ variant: "body1"
1410
+ }, "Stateful Set")), namespace && /* @__PURE__ */ React__default.createElement(Grid, {
1411
+ item: true
1412
+ }, /* @__PURE__ */ React__default.createElement(Chip, {
1413
+ size: "small",
1414
+ label: `namespace: ${namespace}`
1415
+ }))));
1416
+ };
1417
+
1418
+ const StatefulSetSummary = ({
1419
+ statefulset,
1420
+ numberOfCurrentPods,
1421
+ numberOfPodsWithErrors,
1422
+ hpa
1423
+ }) => {
1424
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1425
+ return /* @__PURE__ */ React__default.createElement(Grid, {
1426
+ container: true,
1427
+ direction: "row",
1428
+ justifyContent: "flex-start",
1429
+ alignItems: "center"
1430
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1431
+ xs: 3,
1432
+ item: true
1433
+ }, /* @__PURE__ */ React__default.createElement(StatefulSetDrawer, {
1434
+ statefulset
1435
+ })), /* @__PURE__ */ React__default.createElement(Grid, {
1436
+ item: true,
1437
+ xs: 1
1438
+ }, /* @__PURE__ */ React__default.createElement(Divider, {
1439
+ style: { height: "5em" },
1440
+ orientation: "vertical"
1441
+ })), hpa && /* @__PURE__ */ React__default.createElement(Grid, {
1442
+ item: true,
1443
+ xs: 3
1444
+ }, /* @__PURE__ */ React__default.createElement(HorizontalPodAutoscalerDrawer, {
1445
+ hpa
1446
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1447
+ item: true,
1448
+ container: true,
1449
+ direction: "column",
1450
+ justifyContent: "flex-start",
1451
+ alignItems: "flex-start",
1452
+ spacing: 0
1453
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1454
+ item: true
1455
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1456
+ variant: "subtitle2"
1457
+ }, "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 : "?")), /* @__PURE__ */ React__default.createElement(Grid, {
1458
+ item: true
1459
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1460
+ variant: "subtitle2"
1461
+ }, "current CPU usage:", " ", (_f = (_e = hpa.status) == null ? void 0 : _e.currentCPUUtilizationPercentage) != null ? _f : "?", "%")), /* @__PURE__ */ React__default.createElement(Grid, {
1462
+ item: true
1463
+ }, /* @__PURE__ */ React__default.createElement(Typography, {
1464
+ variant: "subtitle2"
1465
+ }, "target CPU usage:", " ", (_h = (_g = hpa.spec) == null ? void 0 : _g.targetCPUUtilizationPercentage) != null ? _h : "?", "%"))))), /* @__PURE__ */ React__default.createElement(Grid, {
1466
+ item: true,
1467
+ container: true,
1468
+ xs: 3,
1469
+ direction: "column",
1470
+ justifyContent: "flex-start",
1471
+ alignItems: "flex-start"
1472
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1473
+ item: true
1474
+ }, /* @__PURE__ */ React__default.createElement(StatusOK, null, numberOfCurrentPods, " pods")), /* @__PURE__ */ React__default.createElement(Grid, {
1475
+ item: true
1476
+ }, 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"))));
1477
+ };
1478
+ const StatefulSetAccordion = ({
1479
+ statefulset,
1480
+ ownedPods,
1481
+ matchingHpa
1482
+ }) => {
1483
+ const podNamesWithErrors = useContext(PodNamesWithErrorsContext);
1484
+ const podsWithErrors = ownedPods.filter((p) => {
1485
+ var _a, _b;
1486
+ return podNamesWithErrors.has((_b = (_a = p.metadata) == null ? void 0 : _a.name) != null ? _b : "");
1487
+ });
1488
+ return /* @__PURE__ */ React__default.createElement(Accordion, {
1489
+ TransitionProps: { unmountOnExit: true }
1490
+ }, /* @__PURE__ */ React__default.createElement(AccordionSummary, {
1491
+ expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null)
1492
+ }, /* @__PURE__ */ React__default.createElement(StatefulSetSummary, {
1493
+ statefulset,
1494
+ numberOfCurrentPods: ownedPods.length,
1495
+ numberOfPodsWithErrors: podsWithErrors.length,
1496
+ hpa: matchingHpa
1497
+ })), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(PodsTable, {
1498
+ pods: ownedPods,
1499
+ extraColumns: [READY_COLUMNS, RESOURCE_COLUMNS]
1500
+ })));
1501
+ };
1502
+ const StatefulSetsAccordions = ({}) => {
1503
+ const groupedResponses = useContext(GroupedResponsesContext);
1504
+ return /* @__PURE__ */ React__default.createElement(Grid, {
1505
+ container: true,
1506
+ direction: "column",
1507
+ justifyContent: "flex-start",
1508
+ alignItems: "flex-start"
1509
+ }, groupedResponses.statefulsets.map((statefulset, i) => {
1510
+ var _a, _b;
1511
+ return /* @__PURE__ */ React__default.createElement(Grid, {
1512
+ container: true,
1513
+ item: true,
1514
+ key: i,
1515
+ xs: true
1516
+ }, /* @__PURE__ */ React__default.createElement(Grid, {
1517
+ item: true,
1518
+ xs: true
1519
+ }, /* @__PURE__ */ React__default.createElement(StatefulSetAccordion, {
1520
+ matchingHpa: getMatchingHpa({
1521
+ name: (_a = statefulset.metadata) == null ? void 0 : _a.name,
1522
+ namespace: (_b = statefulset.metadata) == null ? void 0 : _b.namespace,
1523
+ kind: "statefulset"
1524
+ }, groupedResponses.horizontalPodAutoscalers),
1525
+ ownedPods: getOwnedResources(statefulset, groupedResponses.pods),
1526
+ statefulset
1527
+ })));
1528
+ }));
1529
+ };
1530
+
1318
1531
  const IngressDrawer = ({
1319
1532
  ingress,
1320
1533
  expanded
@@ -1911,7 +2124,7 @@ const RolloutAccordions = ({
1911
2124
  justifyContent: "flex-start",
1912
2125
  alignItems: "flex-start"
1913
2126
  }, rollouts.map((rollout, i) => {
1914
- var _a;
2127
+ var _a, _b;
1915
2128
  return /* @__PURE__ */ React__default.createElement(Grid, {
1916
2129
  container: true,
1917
2130
  item: true,
@@ -1922,7 +2135,11 @@ const RolloutAccordions = ({
1922
2135
  xs: true
1923
2136
  }, /* @__PURE__ */ React__default.createElement(RolloutAccordion, {
1924
2137
  defaultExpanded,
1925
- matchingHpa: getMatchingHpa((_a = rollout.metadata) == null ? void 0 : _a.name, "rollout", groupedResponses.horizontalPodAutoscalers),
2138
+ matchingHpa: getMatchingHpa({
2139
+ name: (_a = rollout.metadata) == null ? void 0 : _a.name,
2140
+ namespace: (_b = rollout.metadata) == null ? void 0 : _b.namespace,
2141
+ kind: "rollout"
2142
+ }, groupedResponses.horizontalPodAutoscalers),
1926
2143
  ownedPods: getOwnedPodsThroughReplicaSets(rollout, groupedResponses.replicaSets, groupedResponses.pods),
1927
2144
  rollout
1928
2145
  })));
@@ -2130,6 +2347,8 @@ const Cluster = ({ clusterObjects, podsWithErrors }) => {
2130
2347
  item: true
2131
2348
  }, /* @__PURE__ */ React__default.createElement(DeploymentsAccordions, null)), /* @__PURE__ */ React__default.createElement(Grid, {
2132
2349
  item: true
2350
+ }, /* @__PURE__ */ React__default.createElement(StatefulSetsAccordions, null)), /* @__PURE__ */ React__default.createElement(Grid, {
2351
+ item: true
2133
2352
  }, /* @__PURE__ */ React__default.createElement(IngressesAccordions, null)), /* @__PURE__ */ React__default.createElement(Grid, {
2134
2353
  item: true
2135
2354
  }, /* @__PURE__ */ React__default.createElement(ServicesAccordions, null)), /* @__PURE__ */ React__default.createElement(Grid, {