@backstage/plugin-kubernetes 0.4.9 → 0.4.13

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.4.13
4
+
5
+ ### Patch Changes
6
+
7
+ - 9f1362dcc1: Upgrade `@material-ui/lab` to `4.0.0-alpha.57`.
8
+ - Updated dependencies
9
+ - @backstage/core-components@0.4.2
10
+ - @backstage/plugin-catalog-react@0.4.6
11
+ - @backstage/core-plugin-api@0.1.8
12
+
13
+ ## 0.4.12
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+ - @backstage/plugin-catalog-react@0.4.5
19
+ - @backstage/core-components@0.4.0
20
+ - @backstage/catalog-model@0.9.1
21
+
22
+ ## 0.4.11
23
+
24
+ ### Patch Changes
25
+
26
+ - 8bedb75ae: Update Luxon dependency to 2.x
27
+ - Updated dependencies
28
+ - @backstage/core-components@0.3.1
29
+ - @backstage/core-plugin-api@0.1.6
30
+ - @backstage/plugin-catalog-react@0.4.2
31
+
32
+ ## 0.4.10
33
+
34
+ ### Patch Changes
35
+
36
+ - 260c053b9: Fix All Material UI Warnings
37
+ - Updated dependencies
38
+ - @backstage/core-components@0.3.0
39
+ - @backstage/config@0.1.6
40
+ - @backstage/core-plugin-api@0.1.5
41
+ - @backstage/plugin-catalog-react@0.4.1
42
+
3
43
  ## 0.4.9
4
44
 
5
45
  ### Patch Changes
package/dist/index.esm.js CHANGED
@@ -292,7 +292,7 @@ const KubernetesDrawerContent = ({
292
292
  }, /* @__PURE__ */ React__default.createElement(Grid, {
293
293
  container: true,
294
294
  direction: "column",
295
- justify: "flex-start",
295
+ justifyContent: "flex-start",
296
296
  alignItems: "flex-start"
297
297
  }, /* @__PURE__ */ React__default.createElement(Grid, {
298
298
  item: true
@@ -469,7 +469,7 @@ const DeploymentDrawer = ({
469
469
  }, /* @__PURE__ */ React__default.createElement(Grid, {
470
470
  container: true,
471
471
  direction: "column",
472
- justify: "flex-start",
472
+ justifyContent: "flex-start",
473
473
  alignItems: "flex-start",
474
474
  spacing: 0
475
475
  }, /* @__PURE__ */ React__default.createElement(Grid, {
@@ -593,7 +593,7 @@ const DeploymentSummary = ({
593
593
  return /* @__PURE__ */ React__default.createElement(Grid, {
594
594
  container: true,
595
595
  direction: "row",
596
- justify: "flex-start",
596
+ justifyContent: "flex-start",
597
597
  alignItems: "center"
598
598
  }, /* @__PURE__ */ React__default.createElement(Grid, {
599
599
  xs: 3,
@@ -615,7 +615,7 @@ const DeploymentSummary = ({
615
615
  item: true,
616
616
  container: true,
617
617
  direction: "column",
618
- justify: "flex-start",
618
+ justifyContent: "flex-start",
619
619
  alignItems: "flex-start",
620
620
  spacing: 0
621
621
  }, /* @__PURE__ */ React__default.createElement(Grid, {
@@ -635,7 +635,7 @@ const DeploymentSummary = ({
635
635
  container: true,
636
636
  xs: 3,
637
637
  direction: "column",
638
- justify: "flex-start",
638
+ justifyContent: "flex-start",
639
639
  alignItems: "flex-start"
640
640
  }, /* @__PURE__ */ React__default.createElement(Grid, {
641
641
  item: true
@@ -671,7 +671,7 @@ const DeploymentsAccordions = ({}) => {
671
671
  return /* @__PURE__ */ React__default.createElement(Grid, {
672
672
  container: true,
673
673
  direction: "column",
674
- justify: "flex-start",
674
+ justifyContent: "flex-start",
675
675
  alignItems: "flex-start"
676
676
  }, groupedResponses.deployments.map((deployment, i) => {
677
677
  var _a;
@@ -737,7 +737,7 @@ const sortBySeverity = (a, b) => {
737
737
  const ErrorEmptyState = () => {
738
738
  return /* @__PURE__ */ React.createElement(Grid, {
739
739
  container: true,
740
- justify: "space-around",
740
+ justifyContent: "space-around",
741
741
  direction: "row",
742
742
  alignItems: "center",
743
743
  spacing: 2
@@ -985,7 +985,7 @@ const IngressDrawer = ({
985
985
  }, /* @__PURE__ */ React__default.createElement(Grid, {
986
986
  container: true,
987
987
  direction: "column",
988
- justify: "flex-start",
988
+ justifyContent: "flex-start",
989
989
  alignItems: "flex-start",
990
990
  spacing: 0
991
991
  }, /* @__PURE__ */ React__default.createElement(Grid, {
@@ -1004,7 +1004,7 @@ const IngressSummary = ({ingress}) => {
1004
1004
  return /* @__PURE__ */ React__default.createElement(Grid, {
1005
1005
  container: true,
1006
1006
  direction: "row",
1007
- justify: "flex-start",
1007
+ justifyContent: "flex-start",
1008
1008
  alignItems: "center"
1009
1009
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1010
1010
  xs: 3,
@@ -1042,7 +1042,7 @@ const IngressesAccordions = ({}) => {
1042
1042
  return /* @__PURE__ */ React__default.createElement(Grid, {
1043
1043
  container: true,
1044
1044
  direction: "row",
1045
- justify: "flex-start",
1045
+ justifyContent: "flex-start",
1046
1046
  alignItems: "flex-start"
1047
1047
  }, groupedResponses.ingresses.map((ingress, i) => /* @__PURE__ */ React__default.createElement(Grid, {
1048
1048
  item: true,
@@ -1068,7 +1068,7 @@ const ServiceDrawer = ({
1068
1068
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1069
1069
  container: true,
1070
1070
  direction: "column",
1071
- justify: "flex-start",
1071
+ justifyContent: "flex-start",
1072
1072
  alignItems: "flex-start",
1073
1073
  spacing: 0
1074
1074
  }, /* @__PURE__ */ React__default.createElement(Grid, {
@@ -1088,7 +1088,7 @@ const ServiceSummary = ({service}) => {
1088
1088
  return /* @__PURE__ */ React__default.createElement(Grid, {
1089
1089
  container: true,
1090
1090
  direction: "row",
1091
- justify: "flex-start",
1091
+ justifyContent: "flex-start",
1092
1092
  alignItems: "center"
1093
1093
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1094
1094
  xs: 3,
@@ -1143,7 +1143,7 @@ const ServicesAccordions = ({}) => {
1143
1143
  return /* @__PURE__ */ React__default.createElement(Grid, {
1144
1144
  container: true,
1145
1145
  direction: "row",
1146
- justify: "flex-start",
1146
+ justifyContent: "flex-start",
1147
1147
  alignItems: "flex-start"
1148
1148
  }, groupedResponses.services.map((service, i) => /* @__PURE__ */ React__default.createElement(Grid, {
1149
1149
  item: true,
@@ -1167,7 +1167,7 @@ const RolloutDrawer = ({
1167
1167
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1168
1168
  container: true,
1169
1169
  direction: "column",
1170
- justify: "flex-start",
1170
+ justifyContent: "flex-start",
1171
1171
  alignItems: "flex-start",
1172
1172
  spacing: 0
1173
1173
  }, /* @__PURE__ */ React__default.createElement(Grid, {
@@ -1242,7 +1242,7 @@ const RolloutSummary = ({
1242
1242
  return /* @__PURE__ */ React__default.createElement(Grid, {
1243
1243
  container: true,
1244
1244
  direction: "row",
1245
- justify: "flex-start",
1245
+ justifyContent: "flex-start",
1246
1246
  alignItems: "center"
1247
1247
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1248
1248
  xs: 3,
@@ -1264,7 +1264,7 @@ const RolloutSummary = ({
1264
1264
  item: true,
1265
1265
  container: true,
1266
1266
  direction: "column",
1267
- justify: "flex-start",
1267
+ justifyContent: "flex-start",
1268
1268
  alignItems: "flex-start",
1269
1269
  spacing: 0
1270
1270
  }, /* @__PURE__ */ React__default.createElement(Grid, {
@@ -1284,7 +1284,7 @@ const RolloutSummary = ({
1284
1284
  container: true,
1285
1285
  xs: 3,
1286
1286
  direction: "column",
1287
- justify: "flex-start",
1287
+ justifyContent: "flex-start",
1288
1288
  alignItems: "flex-start"
1289
1289
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1290
1290
  item: true
@@ -1354,7 +1354,7 @@ const RolloutAccordions = ({
1354
1354
  return /* @__PURE__ */ React__default.createElement(Grid, {
1355
1355
  container: true,
1356
1356
  direction: "column",
1357
- justify: "flex-start",
1357
+ justifyContent: "flex-start",
1358
1358
  alignItems: "flex-start"
1359
1359
  }, rollouts.map((rollout, i) => {
1360
1360
  var _a;
@@ -1391,7 +1391,7 @@ const DefaultCustomResourceDrawer = ({
1391
1391
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1392
1392
  container: true,
1393
1393
  direction: "column",
1394
- justify: "flex-start",
1394
+ justifyContent: "flex-start",
1395
1395
  alignItems: "flex-start",
1396
1396
  spacing: 0
1397
1397
  }, /* @__PURE__ */ React__default.createElement(Grid, {
@@ -1413,7 +1413,7 @@ const DefaultCustomResourceSummary = ({
1413
1413
  return /* @__PURE__ */ React__default.createElement(Grid, {
1414
1414
  container: true,
1415
1415
  direction: "row",
1416
- justify: "flex-start",
1416
+ justifyContent: "flex-start",
1417
1417
  alignItems: "center"
1418
1418
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1419
1419
  xs: 3,
@@ -1454,7 +1454,7 @@ const DefaultCustomResourceAccordions = ({
1454
1454
  return /* @__PURE__ */ React__default.createElement(Grid, {
1455
1455
  container: true,
1456
1456
  direction: "column",
1457
- justify: "flex-start",
1457
+ justifyContent: "flex-start",
1458
1458
  alignItems: "flex-start"
1459
1459
  }, customResources.map((cr, i) => /* @__PURE__ */ React__default.createElement(Grid, {
1460
1460
  container: true,
@@ -1504,14 +1504,14 @@ const ClusterSummary = ({
1504
1504
  return /* @__PURE__ */ React__default.createElement(Grid, {
1505
1505
  container: true,
1506
1506
  direction: "row",
1507
- justify: "flex-start",
1507
+ justifyContent: "flex-start",
1508
1508
  alignItems: "flex-start"
1509
1509
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1510
1510
  xs: 4,
1511
1511
  item: true,
1512
1512
  container: true,
1513
1513
  direction: "column",
1514
- justify: "flex-start",
1514
+ justifyContent: "flex-start",
1515
1515
  alignItems: "flex-start",
1516
1516
  spacing: 0
1517
1517
  }, /* @__PURE__ */ React__default.createElement(Grid, {
@@ -1533,7 +1533,7 @@ const ClusterSummary = ({
1533
1533
  container: true,
1534
1534
  xs: 3,
1535
1535
  direction: "column",
1536
- justify: "flex-start",
1536
+ justifyContent: "flex-start",
1537
1537
  alignItems: "flex-start"
1538
1538
  }, /* @__PURE__ */ React__default.createElement(Grid, {
1539
1539
  item: true
@@ -1612,7 +1612,7 @@ const KubernetesContent = ({entity}) => {
1612
1612
  container: true
1613
1613
  }, (kubernetesObjects == null ? void 0 : kubernetesObjects.items.length) <= 0 && /* @__PURE__ */ React__default.createElement(Grid, {
1614
1614
  container: true,
1615
- justify: "space-around",
1615
+ justifyContent: "space-around",
1616
1616
  direction: "row",
1617
1617
  alignItems: "center",
1618
1618
  spacing: 2
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/api/KubernetesBackendClient.ts","../src/api/types.ts","../src/kubernetes-auth-provider/types.ts","../src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts","../src/kubernetes-auth-provider/ServiceAccountKubernetesAuthProvider.ts","../src/kubernetes-auth-provider/AwsKubernetesAuthProvider.ts","../src/kubernetes-auth-provider/KubernetesAuthProviders.ts","../src/plugin.ts","../src/components/KubernetesContent/ErrorPanel.tsx","../src/utils/pod.tsx","../src/components/KubernetesDrawer/KubernetesDrawer.tsx","../src/components/Pods/PodDrawer.tsx","../src/components/Pods/PodsTable.tsx","../src/components/DeploymentsAccordions/DeploymentDrawer.tsx","../src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.tsx","../src/utils/owner.ts","../src/hooks/useKubernetesObjects.ts","../src/hooks/PodNamesWithErrors.ts","../src/hooks/GroupedResponses.ts","../src/components/DeploymentsAccordions/DeploymentsAccordions.tsx","../src/components/ErrorReporting/ErrorReporting.tsx","../src/utils/response.ts","../src/error-detection/common.ts","../src/error-detection/pods.ts","../src/error-detection/deployments.ts","../src/error-detection/hpas.ts","../src/error-detection/error-detection.ts","../src/components/IngressesAccordions/IngressDrawer.tsx","../src/components/IngressesAccordions/IngressesAccordions.tsx","../src/components/ServicesAccordions/ServiceDrawer.tsx","../src/components/ServicesAccordions/ServicesAccordions.tsx","../src/components/CustomResources/ArgoRollouts/RolloutDrawer.tsx","../src/components/CustomResources/ArgoRollouts/StepsProgress.tsx","../src/components/CustomResources/ArgoRollouts/Rollout.tsx","../src/components/CustomResources/DefaultCustomResourceDrawer.tsx","../src/components/CustomResources/DefaultCustomResource.tsx","../src/components/CustomResources/CustomResources.tsx","../src/components/KubernetesContent/KubernetesContent.tsx","../src/Router.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesApi } from './types';\nimport {\n KubernetesRequestBody,\n ObjectsByEntityResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';\n\nexport class KubernetesBackendClient implements KubernetesApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly identityApi: IdentityApi;\n\n constructor(options: {\n discoveryApi: DiscoveryApi;\n identityApi: IdentityApi;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.identityApi = options.identityApi;\n }\n\n private async handleResponse(response: Response): Promise<any> {\n if (!response.ok) {\n const payload = await response.text();\n let message;\n switch (response.status) {\n case 404:\n message =\n 'Could not find the Kubernetes Backend (HTTP 404). Make sure the plugin has been fully installed.';\n break;\n default:\n message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;\n }\n throw new Error(message);\n }\n\n return await response.json();\n }\n\n private async postRequired(\n path: string,\n requestBody: KubernetesRequestBody,\n ): Promise<any> {\n const url = `${await this.discoveryApi.getBaseUrl('kubernetes')}${path}`;\n const idToken = await this.identityApi.getIdToken();\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(idToken && { Authorization: `Bearer ${idToken}` }),\n },\n body: JSON.stringify(requestBody),\n });\n\n return this.handleResponse(response);\n }\n\n async getObjectsByEntity(\n requestBody: KubernetesRequestBody,\n ): Promise<ObjectsByEntityResponse> {\n return await this.postRequired(\n `/services/${requestBody.entity.metadata.name}`,\n requestBody,\n );\n }\n\n async getClusters(): Promise<{ name: string; authProvider: string }[]> {\n const url = `${await this.discoveryApi.getBaseUrl('kubernetes')}/clusters`;\n\n const response = await fetch(url, {\n method: 'GET',\n });\n\n return (await this.handleResponse(response)).items;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n KubernetesRequestBody,\n ObjectsByEntityResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\nexport const kubernetesApiRef = createApiRef<KubernetesApi>({\n id: 'plugin.kubernetes.service',\n description:\n 'Used by the Kubernetes plugin to make requests to accompanying backend',\n});\n\nexport interface KubernetesApi {\n getObjectsByEntity(\n requestBody: KubernetesRequestBody,\n ): Promise<ObjectsByEntityResponse>;\n getClusters(): Promise<{ name: string; authProvider: string }[]>;\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\nexport interface KubernetesAuthProvider {\n decorateRequestBodyForAuth(\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody>;\n}\n\nexport const kubernetesAuthProvidersApiRef = createApiRef<KubernetesAuthProvidersApi>(\n {\n id: 'plugin.kubernetes-auth-providers.service',\n description:\n 'Used by the Kubernetes plugin to fetch KubernetesAuthProviders',\n },\n);\n\nexport interface KubernetesAuthProvidersApi {\n decorateRequestBodyForAuth(\n authProvider: string,\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody>;\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthProvider } from './types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\nimport { OAuthApi } from '@backstage/core-plugin-api';\n\nexport class GoogleKubernetesAuthProvider implements KubernetesAuthProvider {\n authProvider: OAuthApi;\n\n constructor(authProvider: OAuthApi) {\n this.authProvider = authProvider;\n }\n\n async decorateRequestBodyForAuth(\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody> {\n const googleAuthToken: string = await this.authProvider.getAccessToken(\n 'https://www.googleapis.com/auth/cloud-platform',\n );\n if ('auth' in requestBody) {\n requestBody.auth!.google = googleAuthToken;\n } else {\n requestBody.auth = { google: googleAuthToken };\n }\n return requestBody;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthProvider } from './types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class ServiceAccountKubernetesAuthProvider\n implements KubernetesAuthProvider {\n async decorateRequestBodyForAuth(\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody> {\n // No-op, with service account for auth, cluster config/details should already have serviceAccountToken\n return requestBody;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthProvider } from './types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class AwsKubernetesAuthProvider implements KubernetesAuthProvider {\n async decorateRequestBodyForAuth(\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody> {\n // No-op, with aws auth, server's AWS credentials are used for access\n return requestBody;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\nimport { KubernetesAuthProvider, KubernetesAuthProvidersApi } from './types';\nimport { GoogleKubernetesAuthProvider } from './GoogleKubernetesAuthProvider';\nimport { ServiceAccountKubernetesAuthProvider } from './ServiceAccountKubernetesAuthProvider';\nimport { AwsKubernetesAuthProvider } from './AwsKubernetesAuthProvider';\nimport { OAuthApi } from '@backstage/core-plugin-api';\n\nexport class KubernetesAuthProviders implements KubernetesAuthProvidersApi {\n private readonly kubernetesAuthProviderMap: Map<\n string,\n KubernetesAuthProvider\n >;\n\n constructor(options: { googleAuthApi: OAuthApi }) {\n this.kubernetesAuthProviderMap = new Map<string, KubernetesAuthProvider>();\n this.kubernetesAuthProviderMap.set(\n 'google',\n new GoogleKubernetesAuthProvider(options.googleAuthApi),\n );\n this.kubernetesAuthProviderMap.set(\n 'serviceAccount',\n new ServiceAccountKubernetesAuthProvider(),\n );\n this.kubernetesAuthProviderMap.set('aws', new AwsKubernetesAuthProvider());\n }\n\n async decorateRequestBodyForAuth(\n authProvider: string,\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody> {\n const kubernetesAuthProvider:\n | KubernetesAuthProvider\n | undefined = this.kubernetesAuthProviderMap.get(authProvider);\n if (kubernetesAuthProvider) {\n return await kubernetesAuthProvider.decorateRequestBodyForAuth(\n requestBody,\n );\n }\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthProvider defined for it`,\n );\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesBackendClient } from './api/KubernetesBackendClient';\nimport { kubernetesApiRef } from './api/types';\nimport { kubernetesAuthProvidersApiRef } from './kubernetes-auth-provider/types';\nimport { KubernetesAuthProviders } from './kubernetes-auth-provider/KubernetesAuthProviders';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n discoveryApiRef,\n identityApiRef,\n googleAuthApiRef,\n createRoutableExtension,\n} from '@backstage/core-plugin-api';\n\nexport const rootCatalogKubernetesRouteRef = createRouteRef({\n path: '*',\n title: 'Kubernetes',\n});\n\nexport const kubernetesPlugin = createPlugin({\n id: 'kubernetes',\n apis: [\n createApiFactory({\n api: kubernetesApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ discoveryApi, identityApi }) =>\n new KubernetesBackendClient({ discoveryApi, identityApi }),\n }),\n createApiFactory({\n api: kubernetesAuthProvidersApiRef,\n deps: { googleAuthApi: googleAuthApiRef },\n factory: ({ googleAuthApi }) => {\n return new KubernetesAuthProviders({ googleAuthApi });\n },\n }),\n ],\n routes: {\n entityContent: rootCatalogKubernetesRouteRef,\n },\n});\n\nexport const EntityKubernetesContent = kubernetesPlugin.provide(\n createRoutableExtension({\n component: () => import('./Router').then(m => m.Router),\n mountPoint: rootCatalogKubernetesRouteRef,\n }),\n);\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { Typography } from '@material-ui/core';\nimport { ClusterObjects } from '@backstage/plugin-kubernetes-common';\nimport { WarningPanel } from '@backstage/core-components';\n\nconst clustersWithErrorsToErrorMessage = (\n clustersWithErrors: ClusterObjects[],\n): React.ReactNode => {\n return clustersWithErrors.map((c, i) => {\n return (\n <div key={i}>\n <Typography variant=\"body2\">{`Cluster: ${c.cluster.name}`}</Typography>\n {c.errors.map((e, j) => {\n return (\n <Typography variant=\"body2\" key={j}>\n {`Error fetching Kubernetes resource: '${e.resourcePath}', error: ${e.errorType}, status code: ${e.statusCode}`}\n </Typography>\n );\n })}\n <br />\n </div>\n );\n });\n};\n\ntype ErrorPanelProps = {\n entityName: string;\n errorMessage?: string;\n clustersWithErrors?: ClusterObjects[];\n children?: React.ReactNode;\n};\n\nexport const ErrorPanel = ({\n entityName,\n errorMessage,\n clustersWithErrors,\n}: ErrorPanelProps) => (\n <WarningPanel\n title=\"There was a problem retrieving Kubernetes objects\"\n 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.`}\n >\n {clustersWithErrors && (\n <div>Errors: {clustersWithErrorsToErrorMessage(clustersWithErrors)}</div>\n )}\n {errorMessage && (\n <Typography variant=\"body2\">Errors: {errorMessage}</Typography>\n )}\n </WarningPanel>\n);\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { V1Pod, V1PodCondition } from '@kubernetes/client-node';\nimport React, { Fragment, ReactNode } from 'react';\nimport { Chip } from '@material-ui/core';\nimport { V1DeploymentCondition } from '@kubernetes/client-node/dist/gen/model/v1DeploymentCondition';\nimport {\n StatusAborted,\n StatusError,\n StatusOK,\n SubvalueCell,\n} from '@backstage/core-components';\n\nexport const imageChips = (pod: V1Pod): ReactNode => {\n const containerStatuses = pod.status?.containerStatuses ?? [];\n const images = containerStatuses.map((cs, i) => {\n return <Chip key={i} label={`${cs.name}=${cs.image}`} size=\"small\" />;\n });\n\n return <div>{images}</div>;\n};\n\nexport const containersReady = (pod: V1Pod): string => {\n const containerStatuses = pod.status?.containerStatuses ?? [];\n const containersReadyItem = containerStatuses.filter(cs => cs.ready).length;\n\n return `${containersReadyItem}/${containerStatuses.length}`;\n};\n\nexport const totalRestarts = (pod: V1Pod): number => {\n const containerStatuses = pod.status?.containerStatuses ?? [];\n return containerStatuses?.reduce((a, b) => a + b.restartCount, 0);\n};\n\nexport const containerStatuses = (pod: V1Pod): ReactNode => {\n const containerStatusesItem = pod.status?.containerStatuses ?? [];\n const errors = containerStatusesItem.reduce((accum, next) => {\n if (next.state === undefined) {\n return accum;\n }\n\n const waiting = next.state.waiting;\n const terminated = next.state.terminated;\n\n const renderCell = (reason: string | undefined) => (\n <Fragment key={`${pod.metadata?.name}-${next.name}`}>\n <SubvalueCell\n value={<StatusError>Container: {next.name}</StatusError>}\n subvalue={reason}\n />\n <br />\n </Fragment>\n );\n\n if (waiting) {\n accum.push(renderCell(waiting.reason));\n }\n\n if (terminated) {\n accum.push(renderCell(terminated.reason));\n }\n\n return accum;\n }, [] as React.ReactNode[]);\n\n if (errors.length === 0) {\n return <StatusOK>OK</StatusOK>;\n }\n\n return errors;\n};\n\nexport const renderCondition = (\n condition: V1PodCondition | V1DeploymentCondition,\n): [string, ReactNode] => {\n const status = condition.status;\n\n if (status === 'True') {\n return [condition.type, <StatusOK>True</StatusOK>];\n } else if (status === 'False') {\n return [\n condition.type,\n <SubvalueCell\n value={<StatusError>False</StatusError>}\n subvalue={condition.message ?? ''}\n />,\n ];\n }\n return [condition.type, <StatusAborted />];\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { ChangeEvent, useState } from 'react';\nimport {\n Button,\n Typography,\n makeStyles,\n IconButton,\n createStyles,\n Theme,\n Drawer,\n Switch,\n FormControlLabel,\n Grid,\n} from '@material-ui/core';\nimport Close from '@material-ui/icons/Close';\nimport { V1ObjectMeta } from '@kubernetes/client-node';\nimport { withStyles } from '@material-ui/core/styles';\nimport jsYaml from 'js-yaml';\nimport {\n CodeSnippet,\n StructuredMetadataTable,\n} from '@backstage/core-components';\n\nconst useDrawerStyles = makeStyles((theme: Theme) =>\n createStyles({\n paper: {\n width: '50%',\n justifyContent: 'space-between',\n padding: theme.spacing(2.5),\n },\n }),\n);\n\nconst useDrawerContentStyles = makeStyles((_: Theme) =>\n createStyles({\n header: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'space-between',\n },\n options: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'flex-end',\n },\n icon: {\n fontSize: 20,\n },\n content: {\n height: '80%',\n },\n }),\n);\n\nconst PodDrawerButton = withStyles({\n root: {\n padding: '6px 5px',\n },\n label: {\n textTransform: 'none',\n },\n})(Button);\n\ninterface KubernetesDrawerable {\n metadata?: V1ObjectMeta;\n}\n\ninterface KubernetesDrawerContentProps<T extends KubernetesDrawerable> {\n toggleDrawer: (e: ChangeEvent<{}>, isOpen: boolean) => void;\n object: T;\n renderObject: (obj: T) => object;\n kind: string;\n}\n\nfunction replaceNullsWithUndefined(someObj: any) {\n const replacer = (_: any, value: any) =>\n String(value) === 'null' || String(value) === 'undefined'\n ? undefined\n : value;\n\n return JSON.parse(JSON.stringify(someObj, replacer));\n}\n\nconst KubernetesDrawerContent = <T extends KubernetesDrawerable>({\n toggleDrawer,\n object,\n renderObject,\n kind,\n}: KubernetesDrawerContentProps<T>) => {\n const [isYaml, setIsYaml] = useState<boolean>(false);\n\n const classes = useDrawerContentStyles();\n\n return (\n <>\n <div className={classes.header}>\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid item>\n <Typography variant=\"h5\">\n {object.metadata?.name ?? 'unknown name'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n {kind}\n </Typography>\n </Grid>\n </Grid>\n <IconButton\n key=\"dismiss\"\n title=\"Close the drawer\"\n onClick={e => toggleDrawer(e, false)}\n color=\"inherit\"\n >\n <Close className={classes.icon} />\n </IconButton>\n </div>\n <div className={classes.options}>\n <FormControlLabel\n control={\n <Switch\n checked={isYaml}\n onChange={event => {\n setIsYaml(event.target.checked);\n }}\n name=\"YAML\"\n />\n }\n label=\"YAML\"\n />\n </div>\n <div className={classes.content}>\n {isYaml && <CodeSnippet language=\"yaml\" text={jsYaml.dump(object)} />}\n {!isYaml && (\n <StructuredMetadataTable\n metadata={renderObject(replaceNullsWithUndefined(object))}\n />\n )}\n </div>\n </>\n );\n};\ninterface KubernetesDrawerProps<T extends KubernetesDrawerable> {\n object: T;\n renderObject: (obj: T) => object;\n buttonVariant?: 'h5' | 'subtitle2';\n kind: string;\n expanded?: boolean;\n children?: React.ReactNode;\n}\n\nexport const KubernetesDrawer = <T extends KubernetesDrawerable>({\n object,\n renderObject,\n kind,\n buttonVariant = 'subtitle2',\n expanded = false,\n children,\n}: KubernetesDrawerProps<T>) => {\n const [isOpen, setIsOpen] = useState(expanded);\n const classes = useDrawerStyles();\n\n const toggleDrawer = (e: ChangeEvent<{}>, newValue: boolean) => {\n e.stopPropagation();\n setIsOpen(newValue);\n };\n\n return (\n <>\n <PodDrawerButton\n onClick={e => toggleDrawer(e, true)}\n onFocus={event => event.stopPropagation()}\n >\n {children === undefined ? (\n <Typography variant={buttonVariant}>\n {object.metadata?.name ?? 'unknown object'}\n </Typography>\n ) : (\n children\n )}\n </PodDrawerButton>\n <Drawer\n classes={{\n paper: classes.paper,\n }}\n anchor=\"right\"\n open={isOpen}\n onClose={(e: any) => toggleDrawer(e, false)}\n onClick={event => event.stopPropagation()}\n >\n <KubernetesDrawerContent\n kind={kind}\n toggleDrawer={toggleDrawer}\n object={object}\n renderObject={renderObject}\n />\n </Drawer>\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1Pod } from '@kubernetes/client-node';\nimport {\n containersReady,\n containerStatuses,\n totalRestarts,\n imageChips,\n renderCondition,\n} from '../../utils/pod';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\n\nexport const PodDrawer = ({\n pod,\n expanded,\n}: {\n pod: V1Pod;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={pod}\n expanded={expanded}\n kind=\"Pod\"\n renderObject={(podObject: V1Pod) => {\n const phase = podObject.status?.phase ?? 'unknown';\n\n const ports =\n podObject.spec?.containers?.map(c => {\n return {\n [c.name]: c.ports,\n };\n }) ?? 'N/A';\n\n const conditions = (podObject.status?.conditions ?? [])\n .map(renderCondition)\n .reduce((accum, next) => {\n accum[next[0]] = next[1];\n return accum;\n }, {} as { [key: string]: React.ReactNode });\n\n return {\n images: imageChips(podObject),\n phase: phase,\n 'Containers Ready': containersReady(podObject),\n 'Total Restarts': totalRestarts(podObject),\n 'Container Statuses': containerStatuses(podObject),\n ...conditions,\n 'Exposed ports': ports,\n };\n }}\n />\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1Pod } from '@kubernetes/client-node';\nimport { PodDrawer } from './PodDrawer';\nimport {\n containersReady,\n containerStatuses,\n totalRestarts,\n} from '../../utils/pod';\nimport { Table, TableColumn } from '@backstage/core-components';\n\nconst columns: TableColumn<V1Pod>[] = [\n {\n title: 'name',\n highlight: true,\n render: (pod: V1Pod) => <PodDrawer pod={pod} />,\n },\n {\n title: 'phase',\n render: (pod: V1Pod) => pod.status?.phase ?? 'unknown',\n },\n {\n title: 'containers ready',\n align: 'center',\n render: containersReady,\n },\n {\n title: 'total restarts',\n align: 'center',\n render: totalRestarts,\n type: 'numeric',\n },\n {\n title: 'status',\n render: containerStatuses,\n },\n];\n\ntype DeploymentTablesProps = {\n pods: V1Pod[];\n children?: React.ReactNode;\n};\n\nexport const PodsTable = ({ pods }: DeploymentTablesProps) => {\n const tableStyle = {\n minWidth: '0',\n width: '100%',\n };\n\n return (\n <div style={tableStyle}>\n <Table\n options={{ paging: true, search: false }}\n data={pods}\n columns={columns}\n />\n </div>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1Deployment } from '@kubernetes/client-node';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\nimport { renderCondition } from '../../utils/pod';\nimport { Typography, Grid } from '@material-ui/core';\n\nexport const DeploymentDrawer = ({\n deployment,\n expanded,\n}: {\n deployment: V1Deployment;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={deployment}\n expanded={expanded}\n kind=\"Deployment\"\n renderObject={(deploymentObj: V1Deployment) => {\n const conditions = (deploymentObj.status?.conditions ?? [])\n .map(renderCondition)\n .reduce((accum, next) => {\n accum[next[0]] = next[1];\n return accum;\n }, {} as { [key: string]: React.ReactNode });\n\n return {\n strategy: deploymentObj.spec?.strategy ?? '???',\n minReadySeconds: deploymentObj.spec?.minReadySeconds ?? '???',\n progressDeadlineSeconds:\n deploymentObj.spec?.progressDeadlineSeconds ?? '???',\n ...conditions,\n };\n }}\n >\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {deployment.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Deployment\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1HorizontalPodAutoscaler } from '@kubernetes/client-node';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\n\nexport const HorizontalPodAutoscalerDrawer = ({\n hpa,\n expanded,\n children,\n}: {\n hpa: V1HorizontalPodAutoscaler;\n expanded?: boolean;\n children?: React.ReactNode;\n}) => {\n return (\n <KubernetesDrawer\n kind=\"HorizontalPodAutoscaler\"\n object={hpa}\n expanded={expanded}\n renderObject={(hpaObject: V1HorizontalPodAutoscaler) => {\n return {\n targetCPUUtilizationPercentage:\n hpaObject.spec?.targetCPUUtilizationPercentage,\n currentCPUUtilizationPercentage:\n hpaObject.status?.currentCPUUtilizationPercentage,\n minReplicas: hpaObject.spec?.minReplicas,\n maxReplicas: hpaObject.spec?.maxReplicas,\n currentReplicas: hpaObject.status?.currentReplicas,\n desiredReplicas: hpaObject.status?.desiredReplicas,\n };\n }}\n >\n {children}\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { V1ObjectMeta } from '@kubernetes/client-node/dist/gen/model/v1ObjectMeta';\nimport {\n V1HorizontalPodAutoscaler,\n V1Pod,\n V1ReplicaSet,\n} from '@kubernetes/client-node';\n\ninterface CanOwn {\n metadata?: V1ObjectMeta;\n}\n\ninterface CanBeOwned {\n metadata?: V1ObjectMeta;\n}\n\nexport function getOwnedResources<R extends CanBeOwned>(\n potentialOwner: CanOwn,\n possiblyOwned: R[],\n): R[] {\n return possiblyOwned.filter(\n p =>\n p.metadata?.ownerReferences?.some(\n o => o.uid === potentialOwner.metadata?.uid,\n ) ?? false,\n );\n}\n\nexport const getOwnedPodsThroughReplicaSets = (\n potentialOwner: CanOwn,\n replicaSets: V1ReplicaSet[],\n pods: V1Pod[],\n) => {\n return getOwnedResources(\n potentialOwner,\n replicaSets.filter(rs => rs.status && rs.status.replicas > 0),\n ).reduce((accum, rs) => {\n return accum.concat(getOwnedResources(rs, pods));\n }, [] as V1Pod[]);\n};\n\nexport const getMatchingHpa = (\n ownerName: string | undefined,\n ownerKind: string,\n hpas: V1HorizontalPodAutoscaler[],\n): V1HorizontalPodAutoscaler | undefined => {\n return hpas.find(hpa => {\n return (\n (hpa.spec?.scaleTargetRef?.kind ?? '').toLowerCase() ===\n ownerKind.toLowerCase() &&\n (hpa.spec?.scaleTargetRef?.name ?? '') ===\n (ownerName ?? 'unknown-deployment')\n );\n });\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { kubernetesApiRef } from '../api/types';\nimport { kubernetesAuthProvidersApiRef } from '../kubernetes-auth-provider/types';\nimport { useEffect, useState } from 'react';\nimport {\n KubernetesRequestBody,\n ObjectsByEntityResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport { useApi } from '@backstage/core-plugin-api';\n\nexport interface KubernetesObjects {\n kubernetesObjects: ObjectsByEntityResponse | undefined;\n error: string | undefined;\n}\n\nexport const useKubernetesObjects = (entity: Entity): KubernetesObjects => {\n const kubernetesApi = useApi(kubernetesApiRef);\n const kubernetesAuthProvidersApi = useApi(kubernetesAuthProvidersApiRef);\n const [kubernetesObjects, setKubernetesObjects] = useState<\n ObjectsByEntityResponse | undefined\n >(undefined);\n\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n (async () => {\n let clusters = [];\n\n try {\n clusters = await kubernetesApi.getClusters();\n } catch (e) {\n setError(e.message);\n return;\n }\n\n const authProviders: string[] = [\n ...new Set(clusters.map(c => c.authProvider)),\n ];\n // For each auth type, invoke decorateRequestBodyForAuth on corresponding KubernetesAuthProvider\n let requestBody: KubernetesRequestBody = {\n entity,\n };\n for (const authProviderStr of authProviders) {\n // Multiple asyncs done sequentially instead of all at once to prevent same requestBody from being modified simultaneously\n try {\n requestBody = await kubernetesAuthProvidersApi.decorateRequestBodyForAuth(\n authProviderStr,\n requestBody,\n );\n } catch (e) {\n setError(e.message);\n return;\n }\n }\n\n try {\n setKubernetesObjects(\n await kubernetesApi.getObjectsByEntity(requestBody),\n );\n } catch (e) {\n setError(e.message);\n return;\n }\n })();\n /* eslint-disable react-hooks/exhaustive-deps */\n }, [entity.metadata.name, kubernetesApi, kubernetesAuthProvidersApi]);\n /* eslint-enable react-hooks/exhaustive-deps */\n\n return {\n kubernetesObjects,\n error,\n };\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nexport const PodNamesWithErrorsContext = React.createContext<Set<string>>(\n new Set<string>(),\n);\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport { GroupedResponses } from '../types/types';\n\nexport const GroupedResponsesContext = React.createContext<GroupedResponses>({\n pods: [],\n replicaSets: [],\n deployments: [],\n services: [],\n configMaps: [],\n horizontalPodAutoscalers: [],\n ingresses: [],\n customResources: [],\n});\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport {\n V1Deployment,\n V1Pod,\n V1HorizontalPodAutoscaler,\n} from '@kubernetes/client-node';\nimport { PodsTable } from '../Pods';\nimport { DeploymentDrawer } from './DeploymentDrawer';\nimport { HorizontalPodAutoscalerDrawer } from '../HorizontalPodAutoscalers';\nimport {\n getOwnedPodsThroughReplicaSets,\n getMatchingHpa,\n} from '../../utils/owner';\nimport {\n GroupedResponsesContext,\n PodNamesWithErrorsContext,\n} from '../../hooks';\nimport { StatusError, StatusOK } from '@backstage/core-components';\n\ntype DeploymentsAccordionsProps = {\n children?: React.ReactNode;\n};\n\ntype DeploymentAccordionProps = {\n deployment: V1Deployment;\n ownedPods: V1Pod[];\n matchingHpa?: V1HorizontalPodAutoscaler;\n children?: React.ReactNode;\n};\n\ntype DeploymentSummaryProps = {\n deployment: V1Deployment;\n numberOfCurrentPods: number;\n numberOfPodsWithErrors: number;\n hpa?: V1HorizontalPodAutoscaler;\n children?: React.ReactNode;\n};\n\nconst DeploymentSummary = ({\n deployment,\n numberOfCurrentPods,\n numberOfPodsWithErrors,\n hpa,\n}: DeploymentSummaryProps) => {\n return (\n <Grid container direction=\"row\" justify=\"flex-start\" alignItems=\"center\">\n <Grid xs={3} item>\n <DeploymentDrawer deployment={deployment} />\n </Grid>\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n {hpa && (\n <Grid item xs={3}>\n <HorizontalPodAutoscalerDrawer hpa={hpa}>\n <Grid\n item\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"subtitle2\">\n min replicas {hpa.spec?.minReplicas ?? '?'} / max replicas{' '}\n {hpa.spec?.maxReplicas ?? '?'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography variant=\"subtitle2\">\n current CPU usage:{' '}\n {hpa.status?.currentCPUUtilizationPercentage ?? '?'}%\n </Typography>\n </Grid>\n <Grid item>\n <Typography variant=\"subtitle2\">\n target CPU usage:{' '}\n {hpa.spec?.targetCPUUtilizationPercentage ?? '?'}%\n </Typography>\n </Grid>\n </Grid>\n </HorizontalPodAutoscalerDrawer>\n </Grid>\n )}\n <Grid\n item\n container\n xs={3}\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid item>\n <StatusOK>{numberOfCurrentPods} pods</StatusOK>\n </Grid>\n <Grid item>\n {numberOfPodsWithErrors > 0 ? (\n <StatusError>\n {numberOfPodsWithErrors} pod\n {numberOfPodsWithErrors > 1 ? 's' : ''} with errors\n </StatusError>\n ) : (\n <StatusOK>No pods with errors</StatusOK>\n )}\n </Grid>\n </Grid>\n </Grid>\n );\n};\n\nconst DeploymentAccordion = ({\n deployment,\n ownedPods,\n matchingHpa,\n}: DeploymentAccordionProps) => {\n const podNamesWithErrors = useContext(PodNamesWithErrorsContext);\n\n const podsWithErrors = ownedPods.filter(p =>\n podNamesWithErrors.has(p.metadata?.name ?? ''),\n );\n\n return (\n <Accordion TransitionProps={{ unmountOnExit: true }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <DeploymentSummary\n deployment={deployment}\n numberOfCurrentPods={ownedPods.length}\n numberOfPodsWithErrors={podsWithErrors.length}\n hpa={matchingHpa}\n />\n </AccordionSummary>\n <AccordionDetails>\n <PodsTable pods={ownedPods} />\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport const DeploymentsAccordions = ({}: DeploymentsAccordionsProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n\n return (\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {groupedResponses.deployments.map((deployment, i) => (\n <Grid container item key={i} xs>\n <Grid item xs>\n <DeploymentAccordion\n matchingHpa={getMatchingHpa(\n deployment.metadata?.name,\n 'deployment',\n groupedResponses.horizontalPodAutoscalers,\n )}\n ownedPods={getOwnedPodsThroughReplicaSets(\n deployment,\n groupedResponses.replicaSets,\n groupedResponses.pods,\n )}\n deployment={deployment}\n />\n </Grid>\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport * as React from 'react';\nimport { DetectedError, DetectedErrorsByCluster } from '../../error-detection';\nimport { Chip, Typography, Grid } from '@material-ui/core';\nimport EmptyStateImage from '../../assets/emptystate.svg';\nimport { Table, TableColumn, InfoCard } from '@backstage/core-components';\n\ntype ErrorReportingProps = {\n detectedErrors: DetectedErrorsByCluster;\n};\n\nconst columns: TableColumn<DetectedError>[] = [\n {\n title: 'cluster',\n width: '15%',\n render: (detectedError: DetectedError) => detectedError.cluster,\n },\n {\n title: 'kind',\n width: '15%',\n render: (detectedError: DetectedError) => detectedError.kind,\n },\n {\n title: 'name',\n width: '30%',\n render: (detectedError: DetectedError) => {\n const errorCount = detectedError.names.length;\n\n if (errorCount === 0) {\n // This shouldn't happen\n return null;\n }\n\n const displayName = detectedError.names[0];\n\n const otherErrorCount = errorCount - 1;\n\n return (\n <>\n {displayName}{' '}\n {otherErrorCount > 0 && (\n <Chip\n label={`+ ${otherErrorCount} other${\n otherErrorCount > 1 ? 's' : ''\n }`}\n size=\"small\"\n />\n )}\n </>\n );\n },\n },\n {\n title: 'messages',\n width: '40%',\n render: (detectedError: DetectedError) => (\n <>\n {detectedError.message.map((m, i) => (\n <div key={i}>{m}</div>\n ))}\n </>\n ),\n },\n];\n\nconst sortBySeverity = (a: DetectedError, b: DetectedError) => {\n if (a.severity < b.severity) {\n return 1;\n } else if (b.severity < a.severity) {\n return -1;\n }\n return 0;\n};\n\nexport const ErrorEmptyState = () => {\n return (\n <Grid\n container\n justify=\"space-around\"\n direction=\"row\"\n alignItems=\"center\"\n spacing={2}\n >\n <Grid item xs={4}>\n <Typography variant=\"h5\">\n Nice! There are no errors to report!\n </Typography>\n </Grid>\n <Grid item xs={4}>\n <img\n src={EmptyStateImage}\n alt=\"EmptyState\"\n data-testid=\"emptyStateImg\"\n />\n </Grid>\n </Grid>\n );\n};\n\nexport const ErrorReporting = ({ detectedErrors }: ErrorReportingProps) => {\n const errors = Array.from(detectedErrors.values())\n .flat()\n .sort(sortBySeverity);\n\n return (\n <>\n {errors.length === 0 ? (\n <InfoCard title=\"Error Reporting\">\n <ErrorEmptyState />\n </InfoCard>\n ) : (\n <Table\n title=\"Error Reporting\"\n data={errors}\n columns={columns}\n options={{ paging: true, search: false }}\n />\n )}\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FetchResponse } from '@backstage/plugin-kubernetes-common';\nimport { GroupedResponses } from '../types/types';\n\n// TODO this could probably be a lodash groupBy\nexport const groupResponses = (\n fetchResponse: FetchResponse[],\n): GroupedResponses => {\n return fetchResponse.reduce(\n (prev, next) => {\n switch (next.type) {\n case 'deployments':\n prev.deployments.push(...next.resources);\n break;\n case 'pods':\n prev.pods.push(...next.resources);\n break;\n case 'replicasets':\n prev.replicaSets.push(...next.resources);\n break;\n case 'services':\n prev.services.push(...next.resources);\n break;\n case 'configmaps':\n prev.configMaps.push(...next.resources);\n break;\n case 'horizontalpodautoscalers':\n prev.horizontalPodAutoscalers.push(...next.resources);\n break;\n case 'ingresses':\n prev.ingresses.push(...next.resources);\n break;\n case 'customresources':\n prev.customResources.push(...next.resources);\n break;\n default:\n }\n return prev;\n },\n {\n pods: [],\n replicaSets: [],\n deployments: [],\n services: [],\n configMaps: [],\n horizontalPodAutoscalers: [],\n ingresses: [],\n customResources: [],\n } as GroupedResponses,\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DetectedError,\n ErrorDetectable,\n ErrorDetectableKind,\n ErrorMapper,\n} from './types';\n\n// Run through the each error mapper for each object\n// returning a deduplicated (mostly) result\nexport const detectErrorsInObjects = <T extends ErrorDetectable>(\n objects: T[],\n kind: ErrorDetectableKind,\n clusterName: string,\n errorMappers: ErrorMapper<T>[],\n): DetectedError[] => {\n // Build up a map of errors\n // key: the joined message produced by an error\n // value: the error\n const errors = new Map<string, DetectedError>();\n\n for (const object of objects) {\n for (const errorMapper of errorMappers) {\n if (errorMapper.errorExists(object)) {\n const message = errorMapper.messageAccessor(object);\n\n // TODO This is not perfect as errors with uuid/hashes/date/times will not be caught by this\n const dedupKey = message.join('');\n\n const value = errors.get(dedupKey);\n\n const name = object.metadata?.name ?? 'unknown';\n\n if (value !== undefined) {\n // This gets translated into the Chip \"+5 others\"\n // in the ErrorReporting component\n // but we need to keep the names so we can easily\n // find which objects owns the error later\n value.names.push(name);\n errors.set(dedupKey, value);\n } else {\n errors.set(dedupKey, {\n cluster: clusterName,\n kind: kind,\n names: [name],\n message: message,\n severity: errorMapper.severity,\n });\n }\n }\n }\n }\n\n return Array.from(errors.values());\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { V1Pod } from '@kubernetes/client-node';\nimport { totalRestarts } from '../utils/pod';\nimport { DetectedError, ErrorMapper } from './types';\nimport { detectErrorsInObjects } from './common';\n\nconst podErrorMappers: ErrorMapper<V1Pod>[] = [\n {\n severity: 5,\n errorExplanation: 'status-message',\n errorExists: pod => {\n return pod.status?.message !== undefined;\n },\n messageAccessor: pod => {\n return [pod.status?.message ?? ''];\n },\n },\n {\n severity: 4,\n errorExplanation: 'containers-restarting',\n errorExists: pod => {\n // TODO magic number\n return totalRestarts(pod) > 3;\n },\n messageAccessor: pod => {\n return (pod.status?.containerStatuses ?? [])\n .filter(cs => cs.restartCount > 0)\n .map(cs => `container=${cs.name} restarted ${cs.restartCount} times`);\n },\n },\n {\n severity: 5,\n errorExplanation: 'condition-message-present',\n errorExists: pod => {\n return (pod.status?.conditions ?? []).some(c => c.message !== undefined);\n },\n messageAccessor: pod => {\n return (pod.status?.conditions ?? [])\n .filter(c => c.message !== undefined)\n .map(c => c.message ?? '');\n },\n },\n {\n severity: 6,\n errorExplanation: 'container-waiting',\n errorExists: pod => {\n return (pod.status?.containerStatuses ?? []).some(\n cs => cs.state?.waiting?.message !== undefined,\n );\n },\n messageAccessor: pod => {\n return (pod.status?.containerStatuses ?? [])\n .filter(cs => cs.state?.waiting?.message !== undefined)\n .map(cs => cs.state?.waiting?.message ?? '');\n },\n },\n {\n severity: 4,\n errorExplanation: 'container-last-state-error',\n errorExists: pod => {\n return (pod.status?.containerStatuses ?? []).some(\n cs => (cs.lastState?.terminated?.reason ?? '') === 'Error',\n );\n },\n messageAccessor: pod => {\n return (pod.status?.containerStatuses ?? [])\n .filter(cs => (cs.lastState?.terminated?.reason ?? '') === 'Error')\n .map(\n cs =>\n `container=${cs.name} exited with error code (${cs.lastState?.terminated?.exitCode})`,\n );\n },\n },\n];\n\nexport const detectErrorsInPods = (\n pods: V1Pod[],\n clusterName: string,\n): DetectedError[] =>\n detectErrorsInObjects(pods, 'Pod', clusterName, podErrorMappers);\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DetectedError, ErrorMapper } from './types';\nimport { V1Deployment } from '@kubernetes/client-node';\nimport { detectErrorsInObjects } from './common';\n\nconst deploymentErrorMappers: ErrorMapper<V1Deployment>[] = [\n {\n // this is probably important\n severity: 6,\n errorExplanation: 'condition-message-present',\n errorExists: deployment => {\n return (deployment.status?.conditions ?? [])\n .filter(c => c.status === 'False')\n .some(c => c.message !== undefined);\n },\n messageAccessor: deployment => {\n return (deployment.status?.conditions ?? [])\n .filter(c => c.status === 'False')\n .filter(c => c.message !== undefined)\n .map(c => c.message ?? '');\n },\n },\n];\n\nexport const detectErrorsInDeployments = (\n deployments: V1Deployment[],\n clusterName: string,\n): DetectedError[] =>\n detectErrorsInObjects(\n deployments,\n 'Deployment',\n clusterName,\n deploymentErrorMappers,\n );\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { V1HorizontalPodAutoscaler } from '@kubernetes/client-node';\nimport { DetectedError, ErrorMapper } from './types';\nimport { detectErrorsInObjects } from './common';\n\nconst hpaErrorMappers: ErrorMapper<V1HorizontalPodAutoscaler>[] = [\n {\n // this is probably important\n severity: 8,\n errorExplanation: 'hpa-max-current-replicas',\n errorExists: hpa => {\n return (hpa.spec?.maxReplicas ?? -1) === hpa.status?.currentReplicas;\n },\n messageAccessor: hpa => {\n return [\n `Current number of replicas (${\n hpa.status?.currentReplicas\n }) is equal to the configured max number of replicas (${\n hpa.spec?.maxReplicas ?? -1\n })`,\n ];\n },\n },\n];\n\nexport const detectErrorsInHpa = (\n hpas: V1HorizontalPodAutoscaler[],\n clusterName: string,\n): DetectedError[] =>\n detectErrorsInObjects(\n hpas,\n 'HorizontalPodAutoscaler',\n clusterName,\n hpaErrorMappers,\n );\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DetectedError, DetectedErrorsByCluster } from './types';\nimport { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common';\nimport { groupResponses } from '../utils/response';\nimport { detectErrorsInPods } from './pods';\nimport { detectErrorsInDeployments } from './deployments';\nimport { detectErrorsInHpa } from './hpas';\n\n// For each cluster try to find errors in each of the object types provided\n// returning a map of cluster names to errors in that cluster\nexport const detectErrors = (\n objects: ObjectsByEntityResponse,\n): DetectedErrorsByCluster => {\n const errors: DetectedErrorsByCluster = new Map<string, DetectedError[]>();\n\n for (const clusterResponse of objects.items) {\n let clusterErrors: DetectedError[] = [];\n\n const groupedResponses = groupResponses(clusterResponse.resources);\n\n clusterErrors = clusterErrors.concat(\n detectErrorsInPods(groupedResponses.pods, clusterResponse.cluster.name),\n );\n\n clusterErrors = clusterErrors.concat(\n detectErrorsInDeployments(\n groupedResponses.deployments,\n clusterResponse.cluster.name,\n ),\n );\n\n clusterErrors = clusterErrors.concat(\n detectErrorsInHpa(\n groupedResponses.horizontalPodAutoscalers,\n clusterResponse.cluster.name,\n ),\n );\n\n errors.set(clusterResponse.cluster.name, clusterErrors);\n }\n\n return errors;\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { ExtensionsV1beta1Ingress } from '@kubernetes/client-node';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\nimport { Typography, Grid } from '@material-ui/core';\n\nexport const IngressDrawer = ({\n ingress,\n expanded,\n}: {\n ingress: ExtensionsV1beta1Ingress;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={ingress}\n expanded={expanded}\n kind=\"Ingress\"\n renderObject={(ingressObject: ExtensionsV1beta1Ingress) => {\n return ingressObject.spec || {};\n }}\n >\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {ingress.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Ingress\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { ExtensionsV1beta1Ingress } from '@kubernetes/client-node';\nimport { IngressDrawer } from './IngressDrawer';\nimport { GroupedResponsesContext } from '../../hooks';\nimport { StructuredMetadataTable } from '@backstage/core-components';\n\ntype IngressesAccordionsProps = {};\n\ntype IngressAccordionProps = {\n ingress: ExtensionsV1beta1Ingress;\n};\n\ntype IngressSummaryProps = {\n ingress: ExtensionsV1beta1Ingress;\n};\n\nconst IngressSummary = ({ ingress }: IngressSummaryProps) => {\n return (\n <Grid container direction=\"row\" justify=\"flex-start\" alignItems=\"center\">\n <Grid xs={3} item>\n <IngressDrawer ingress={ingress} />\n </Grid>\n\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n </Grid>\n );\n};\n\ntype IngressCardProps = {\n ingress: ExtensionsV1beta1Ingress;\n};\n\nconst IngressCard = ({ ingress }: IngressCardProps) => {\n return (\n <StructuredMetadataTable\n metadata={{\n ...ingress.spec,\n }}\n />\n );\n};\n\nconst IngressAccordion = ({ ingress }: IngressAccordionProps) => {\n return (\n <Accordion TransitionProps={{ unmountOnExit: true }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <IngressSummary ingress={ingress} />\n </AccordionSummary>\n <AccordionDetails>\n <IngressCard ingress={ingress} />\n </AccordionDetails>\n </Accordion>\n );\n};\nexport const IngressesAccordions = ({}: IngressesAccordionsProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n return (\n <Grid\n container\n direction=\"row\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {groupedResponses.ingresses.map((ingress, i) => (\n <Grid item key={i} xs>\n <IngressAccordion ingress={ingress} />\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1Service } from '@kubernetes/client-node';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\nimport { Typography, Grid } from '@material-ui/core';\n\nexport const ServiceDrawer = ({\n service,\n expanded,\n}: {\n service: V1Service;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={service}\n expanded={expanded}\n kind=\"Service\"\n renderObject={(serviceObject: V1Service) => {\n return serviceObject.spec || {};\n }}\n >\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {service.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Service\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { V1Service } from '@kubernetes/client-node';\nimport { ServiceDrawer } from './ServiceDrawer';\nimport { GroupedResponsesContext } from '../../hooks';\nimport { StructuredMetadataTable } from '@backstage/core-components';\n\ntype ServiceSummaryProps = {\n service: V1Service;\n};\n\nconst ServiceSummary = ({ service }: ServiceSummaryProps) => {\n return (\n <Grid container direction=\"row\" justify=\"flex-start\" alignItems=\"center\">\n <Grid xs={3} item>\n <ServiceDrawer service={service} />\n </Grid>\n\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n\n <Grid item>\n <Typography variant=\"subtitle2\">\n Type: {service.spec?.type ?? '?'}\n </Typography>\n </Grid>\n </Grid>\n );\n};\n\ntype ServiceCardProps = {\n service: V1Service;\n};\n\nconst ServiceCard = ({ service }: ServiceCardProps) => {\n const metadata: any = {};\n\n if (service.status?.loadBalancer?.ingress?.length ?? -1 > 0) {\n metadata.loadbalancer = service.status?.loadBalancer;\n }\n\n if (service.spec?.type === 'ClusterIP') {\n metadata.clusterIP = service.spec.clusterIP;\n }\n if (service.spec?.type === 'ExternalName') {\n metadata.externalName = service.spec.externalName;\n }\n\n return (\n <StructuredMetadataTable\n metadata={{\n type: service.spec?.type,\n ports: service.spec?.ports,\n ...metadata,\n }}\n />\n );\n};\n\ntype ServicesAccordionsProps = {};\n\ntype ServiceAccordionProps = {\n service: V1Service;\n};\n\nconst ServiceAccordion = ({ service }: ServiceAccordionProps) => {\n return (\n <Accordion TransitionProps={{ unmountOnExit: true }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <ServiceSummary service={service} />\n </AccordionSummary>\n <AccordionDetails>\n <ServiceCard service={service} />\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport const ServicesAccordions = ({}: ServicesAccordionsProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n return (\n <Grid\n container\n direction=\"row\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {groupedResponses.services.map((service, i) => (\n <Grid item key={i} xs>\n <ServiceAccordion service={service} />\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { KubernetesDrawer } from '../../KubernetesDrawer/KubernetesDrawer';\nimport { Typography, Grid } from '@material-ui/core';\n\nexport const RolloutDrawer = ({\n rollout,\n expanded,\n}: {\n rollout: any;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={rollout}\n expanded={expanded}\n kind=\"Rollout\"\n renderObject={() => ({})}\n >\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {rollout.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Rollout\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { Step, StepLabel, Stepper } from '@material-ui/core';\nimport {\n ArgoRolloutCanaryStep,\n SetWeightStep,\n PauseStep,\n AnalysisStep,\n} from './types';\n\ninterface StepsProgressProps {\n currentStepIndex: number;\n aborted: boolean;\n steps: ArgoRolloutCanaryStep[];\n children?: React.ReactNode;\n}\n\nconst isSetWeightStep = (step: ArgoRolloutCanaryStep): step is SetWeightStep =>\n step.hasOwnProperty('setWeight');\n\nconst isPauseStep = (step: ArgoRolloutCanaryStep): step is PauseStep =>\n step.hasOwnProperty('pause');\n\nconst isAnalysisStep = (step: ArgoRolloutCanaryStep): step is AnalysisStep =>\n step.hasOwnProperty('analysis');\n\nconst createLabelForStep = (step: ArgoRolloutCanaryStep): React.ReactNode => {\n if (isSetWeightStep(step)) {\n return `setWeight ${step.setWeight}%`;\n } else if (isPauseStep(step)) {\n return step.pause.duration === undefined\n ? 'infinite pause'\n : `pause for ${step.pause.duration}`;\n } else if (isAnalysisStep(step)) {\n return (\n <div>\n <p>analysis templates:</p>\n {step.analysis.templates.map((t, i) => (\n <p key={i}>{`${t.templateName}${\n t.clusterScope ? ' (cluster scoped)' : ''\n }`}</p>\n ))}\n </div>\n );\n }\n return 'unknown step';\n};\n\nexport const StepsProgress = ({\n currentStepIndex,\n aborted,\n steps,\n}: StepsProgressProps) => {\n // If the activeStep is greater/equal to the number of steps\n // Then the canary is being promoted\n // Increase the step index to mark the 'canary promoted' step as done also\n const activeStepIndex =\n currentStepIndex >= steps.length ? currentStepIndex + 1 : currentStepIndex;\n\n /*\n * When the Rollout is aborted set the active step to -1\n * otherwise it appears to always be on the first step\n */\n return (\n <Stepper activeStep={aborted ? -1 : activeStepIndex} alternativeLabel>\n {steps\n .map((step, i) => (\n <Step key={i}>\n <StepLabel data-testid={`step-${i}`}>\n {createLabelForStep(step)}\n </StepLabel>\n </Step>\n ))\n .concat(\n <Step key=\"-1\">\n <StepLabel data-testid=\"step--1\">Canary promoted</StepLabel>\n </Step>,\n )}\n </Stepper>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { V1Pod, V1HorizontalPodAutoscaler } from '@kubernetes/client-node';\nimport { PodsTable } from '../../Pods';\nimport { HorizontalPodAutoscalerDrawer } from '../../HorizontalPodAutoscalers';\nimport { RolloutDrawer } from './RolloutDrawer';\nimport PauseIcon from '@material-ui/icons/Pause';\nimport ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';\nimport { DateTime } from 'luxon';\nimport { StepsProgress } from './StepsProgress';\nimport {\n PodNamesWithErrorsContext,\n GroupedResponsesContext,\n} from '../../../hooks';\nimport {\n getMatchingHpa,\n getOwnedPodsThroughReplicaSets,\n} from '../../../utils/owner';\nimport { StatusError, StatusOK } from '@backstage/core-components';\n\ntype RolloutAccordionsProps = {\n rollouts: any[];\n defaultExpanded?: boolean;\n children?: React.ReactNode;\n};\n\ntype RolloutAccordionProps = {\n rollout: any;\n ownedPods: V1Pod[];\n defaultExpanded?: boolean;\n matchingHpa?: V1HorizontalPodAutoscaler;\n children?: React.ReactNode;\n};\n\ntype RolloutSummaryProps = {\n rollout: any;\n numberOfCurrentPods: number;\n numberOfPodsWithErrors: number;\n hpa?: V1HorizontalPodAutoscaler;\n children?: React.ReactNode;\n};\n\nconst AbortedTitle = (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n }}\n >\n <ErrorOutlineIcon />\n <Typography variant=\"subtitle1\">Aborted</Typography>\n </div>\n);\n\nconst findAbortedMessage = (rollout: any): string | undefined =>\n rollout.status?.conditions?.find(\n (c: any) =>\n c.type === 'Progressing' &&\n c.status === 'False' &&\n c.reason === 'RolloutAborted',\n )?.message;\n\nconst RolloutSummary = ({\n rollout,\n numberOfCurrentPods,\n numberOfPodsWithErrors,\n hpa,\n}: RolloutSummaryProps) => {\n const pauseTime: string | undefined = rollout.status?.pauseConditions?.find(\n (p: any) => p.reason === 'CanaryPauseStep',\n )?.startTime;\n const abortedMessage = findAbortedMessage(rollout);\n\n return (\n <Grid container direction=\"row\" justify=\"flex-start\" alignItems=\"center\">\n <Grid xs={3} item>\n <RolloutDrawer rollout={rollout} />\n </Grid>\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n {hpa && (\n <Grid item xs={3}>\n <HorizontalPodAutoscalerDrawer hpa={hpa}>\n <Grid\n item\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"subtitle2\">\n min replicas {hpa.spec?.minReplicas ?? '?'} / max replicas{' '}\n {hpa.spec?.maxReplicas ?? '?'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography variant=\"subtitle2\">\n current CPU usage:{' '}\n {hpa.status?.currentCPUUtilizationPercentage ?? '?'}%\n </Typography>\n </Grid>\n <Grid item>\n <Typography variant=\"subtitle2\">\n target CPU usage:{' '}\n {hpa.spec?.targetCPUUtilizationPercentage ?? '?'}%\n </Typography>\n </Grid>\n </Grid>\n </HorizontalPodAutoscalerDrawer>\n </Grid>\n )}\n <Grid\n item\n container\n xs={3}\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid item>\n <StatusOK>{numberOfCurrentPods} pods</StatusOK>\n </Grid>\n <Grid item>\n {numberOfPodsWithErrors > 0 ? (\n <StatusError>\n {numberOfPodsWithErrors} pod\n {numberOfPodsWithErrors > 1 ? 's' : ''} with errors\n </StatusError>\n ) : (\n <StatusOK>No pods with errors</StatusOK>\n )}\n </Grid>\n </Grid>\n {pauseTime && (\n <Grid item xs={3}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n }}\n >\n <PauseIcon />\n <Typography variant=\"subtitle1\">\n Paused ({DateTime.fromISO(pauseTime).toRelative({ locale: 'en' })}\n )\n </Typography>\n </div>\n </Grid>\n )}\n {abortedMessage && (\n <Grid item xs={3}>\n {AbortedTitle}\n </Grid>\n )}\n </Grid>\n );\n};\n\nconst RolloutAccordion = ({\n rollout,\n ownedPods,\n matchingHpa,\n defaultExpanded,\n}: RolloutAccordionProps) => {\n const podNamesWithErrors = useContext(PodNamesWithErrorsContext);\n\n const podsWithErrors = ownedPods.filter(p =>\n podNamesWithErrors.has(p.metadata?.name ?? ''),\n );\n\n const currentStepIndex = rollout.status?.currentStepIndex ?? 0;\n const abortedMessage = findAbortedMessage(rollout);\n\n return (\n <Accordion\n defaultExpanded={defaultExpanded}\n TransitionProps={{ unmountOnExit: true }}\n >\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <RolloutSummary\n rollout={rollout}\n numberOfCurrentPods={ownedPods.length}\n numberOfPodsWithErrors={podsWithErrors.length}\n hpa={matchingHpa}\n />\n </AccordionSummary>\n <AccordionDetails>\n <div style={{ width: '100%' }}>\n <div>\n <Typography variant=\"h6\">Rollout status</Typography>\n </div>\n <div style={{ margin: '1rem' }}>\n {abortedMessage && (\n <>\n {AbortedTitle}\n <Typography variant=\"subtitle2\">{abortedMessage}</Typography>\n </>\n )}\n <StepsProgress\n aborted={abortedMessage !== undefined}\n steps={rollout.spec?.strategy?.canary?.steps ?? []}\n currentStepIndex={currentStepIndex}\n />\n </div>\n <div>\n <PodsTable pods={ownedPods} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport const RolloutAccordions = ({\n rollouts,\n defaultExpanded = false,\n}: RolloutAccordionsProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n\n return (\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {rollouts.map((rollout, i) => (\n <Grid container item key={i} xs>\n <Grid item xs>\n <RolloutAccordion\n defaultExpanded={defaultExpanded}\n matchingHpa={getMatchingHpa(\n rollout.metadata?.name,\n 'rollout',\n groupedResponses.horizontalPodAutoscalers,\n )}\n ownedPods={getOwnedPodsThroughReplicaSets(\n rollout,\n groupedResponses.replicaSets,\n groupedResponses.pods,\n )}\n rollout={rollout}\n />\n </Grid>\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\nimport { Typography, Grid } from '@material-ui/core';\n\nconst capitalize = (str: string) =>\n str.charAt(0).toLocaleUpperCase('en-US') + str.slice(1);\n\nexport const DefaultCustomResourceDrawer = ({\n customResource,\n customResourceName,\n expanded,\n}: {\n customResource: any;\n customResourceName: string;\n expanded?: boolean;\n}) => {\n const capitalizedName = capitalize(customResourceName);\n\n return (\n <KubernetesDrawer\n object={customResource}\n expanded={expanded}\n kind={capitalizedName}\n renderObject={cr => cr}\n >\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {customResource.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n {capitalizedName}\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { DefaultCustomResourceDrawer } from './DefaultCustomResourceDrawer';\nimport { StructuredMetadataTable } from '@backstage/core-components';\n\ntype DefaultCustomResourceAccordionsProps = {\n customResources: any[];\n customResourceName: string;\n defaultExpanded?: boolean;\n children?: React.ReactNode;\n};\n\ntype DefaultCustomResourceAccordionProps = {\n customResource: any;\n customResourceName: string;\n defaultExpanded?: boolean;\n children?: React.ReactNode;\n};\n\ntype DefaultCustomResourceSummaryProps = {\n customResource: any;\n customResourceName: string;\n children?: React.ReactNode;\n};\n\nconst DefaultCustomResourceSummary = ({\n customResource,\n customResourceName,\n}: DefaultCustomResourceSummaryProps) => {\n return (\n <Grid container direction=\"row\" justify=\"flex-start\" alignItems=\"center\">\n <Grid xs={3} item>\n <DefaultCustomResourceDrawer\n customResource={customResource}\n customResourceName={customResourceName}\n />\n </Grid>\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n </Grid>\n );\n};\n\nconst DefaultCustomResourceAccordion = ({\n customResource,\n customResourceName,\n defaultExpanded,\n}: DefaultCustomResourceAccordionProps) => {\n return (\n <Accordion\n defaultExpanded={defaultExpanded}\n TransitionProps={{ unmountOnExit: true }}\n >\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <DefaultCustomResourceSummary\n customResource={customResource}\n customResourceName={customResourceName}\n />\n </AccordionSummary>\n <AccordionDetails>\n {customResource.hasOwnProperty('status') && (\n <StructuredMetadataTable metadata={customResource.status} />\n )}\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport const DefaultCustomResourceAccordions = ({\n customResources,\n customResourceName,\n defaultExpanded = false,\n}: DefaultCustomResourceAccordionsProps) => {\n return (\n <Grid\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {customResources.map((cr, i) => (\n <Grid container item key={i} xs>\n <Grid item xs>\n <DefaultCustomResourceAccordion\n defaultExpanded={defaultExpanded}\n customResource={cr}\n customResourceName={customResourceName}\n />\n </Grid>\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport lodash, { Dictionary } from 'lodash';\nimport { RolloutAccordions } from './ArgoRollouts';\nimport { DefaultCustomResourceAccordions } from './DefaultCustomResource';\nimport { GroupedResponsesContext } from '../../hooks';\n\ninterface CustomResourcesProps {\n children?: React.ReactNode;\n}\n\nconst kindToResource = (customResources: any[]): Dictionary<any[]> => {\n return lodash.groupBy(customResources, value => {\n return value.kind;\n });\n};\n\nexport const CustomResources = ({}: CustomResourcesProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n const kindToResourceMap = kindToResource(groupedResponses.customResources);\n\n return (\n <>\n {Object.entries(kindToResourceMap).map(([kind, resources], i) => {\n switch (kind) {\n case 'Rollout':\n return <RolloutAccordions key={i} rollouts={resources} />;\n default:\n return (\n <DefaultCustomResourceAccordions\n key={i}\n customResources={resources}\n customResourceName={kind}\n />\n );\n }\n })}\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { Entity } from '@backstage/catalog-model';\nimport { ClusterObjects } from '@backstage/plugin-kubernetes-common';\nimport { ErrorPanel } from './ErrorPanel';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { DeploymentsAccordions } from '../DeploymentsAccordions';\nimport { ErrorReporting } from '../ErrorReporting';\nimport { groupResponses } from '../../utils/response';\nimport { DetectedError, detectErrors } from '../../error-detection';\nimport { IngressesAccordions } from '../IngressesAccordions';\nimport { ServicesAccordions } from '../ServicesAccordions';\nimport { CustomResources } from '../CustomResources';\nimport EmptyStateImage from '../../assets/emptystate.svg';\nimport {\n GroupedResponsesContext,\n PodNamesWithErrorsContext,\n useKubernetesObjects,\n} from '../../hooks';\n\nimport {\n Content,\n Page,\n Progress,\n StatusError,\n StatusOK,\n} from '@backstage/core-components';\n\ntype ClusterSummaryProps = {\n clusterName: string;\n totalNumberOfPods: number;\n numberOfPodsWithErrors: number;\n children?: React.ReactNode;\n};\n\nconst ClusterSummary = ({\n clusterName,\n totalNumberOfPods,\n numberOfPodsWithErrors,\n}: ClusterSummaryProps) => {\n return (\n <Grid\n container\n direction=\"row\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid\n xs={4}\n item\n container\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item xs>\n <Typography variant=\"h3\">{clusterName}</Typography>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Cluster\n </Typography>\n </Grid>\n </Grid>\n <Grid item xs={1}>\n <Divider style={{ height: '4em' }} orientation=\"vertical\" />\n </Grid>\n <Grid\n item\n container\n xs={3}\n direction=\"column\"\n justify=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid item>\n <StatusOK>{totalNumberOfPods} pods</StatusOK>\n </Grid>\n <Grid item>\n {numberOfPodsWithErrors > 0 ? (\n <StatusError>{numberOfPodsWithErrors} pods with errors</StatusError>\n ) : (\n <StatusOK>No pods with errors</StatusOK>\n )}\n </Grid>\n </Grid>\n </Grid>\n );\n};\n\ntype ClusterProps = {\n clusterObjects: ClusterObjects;\n podsWithErrors: Set<string>;\n children?: React.ReactNode;\n};\n\nconst Cluster = ({ clusterObjects, podsWithErrors }: ClusterProps) => {\n const groupedResponses = groupResponses(clusterObjects.resources);\n return (\n <GroupedResponsesContext.Provider value={groupedResponses}>\n <PodNamesWithErrorsContext.Provider value={podsWithErrors}>\n <Accordion TransitionProps={{ unmountOnExit: true }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <ClusterSummary\n clusterName={clusterObjects.cluster.name}\n totalNumberOfPods={groupedResponses.pods.length}\n numberOfPodsWithErrors={podsWithErrors.size}\n />\n </AccordionSummary>\n <AccordionDetails>\n <Grid container direction=\"column\">\n <Grid item>\n <CustomResources />\n </Grid>\n <Grid item>\n <DeploymentsAccordions />\n </Grid>\n <Grid item>\n <IngressesAccordions />\n </Grid>\n <Grid item>\n <ServicesAccordions />\n </Grid>\n </Grid>\n </AccordionDetails>\n </Accordion>\n </PodNamesWithErrorsContext.Provider>\n </GroupedResponsesContext.Provider>\n );\n};\n\ntype KubernetesContentProps = { entity: Entity; children?: React.ReactNode };\n\nexport const KubernetesContent = ({ entity }: KubernetesContentProps) => {\n const { kubernetesObjects, error } = useKubernetesObjects(entity);\n\n const clustersWithErrors =\n kubernetesObjects?.items.filter(r => r.errors.length > 0) ?? [];\n\n const detectedErrors =\n kubernetesObjects !== undefined\n ? detectErrors(kubernetesObjects)\n : new Map<string, DetectedError[]>();\n\n return (\n <Page themeId=\"tool\">\n <Content>\n {kubernetesObjects === undefined && error === undefined && <Progress />}\n\n {/* errors retrieved from the kubernetes clusters */}\n {clustersWithErrors.length > 0 && (\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <ErrorPanel\n entityName={entity.metadata.name}\n clustersWithErrors={clustersWithErrors}\n />\n </Grid>\n </Grid>\n )}\n\n {/* other errors */}\n {error !== undefined && (\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <ErrorPanel\n entityName={entity.metadata.name}\n errorMessage={error}\n />\n </Grid>\n </Grid>\n )}\n\n {kubernetesObjects && (\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <ErrorReporting detectedErrors={detectedErrors} />\n </Grid>\n <Grid item>\n <Divider />\n </Grid>\n <Grid item>\n <Typography variant=\"h3\">Your Clusters</Typography>\n </Grid>\n <Grid item container>\n {kubernetesObjects?.items.length <= 0 && (\n <Grid\n container\n justify=\"space-around\"\n direction=\"row\"\n alignItems=\"center\"\n spacing={2}\n >\n <Grid item xs={4}>\n <Typography variant=\"h5\">\n No resources on any known clusters for{' '}\n {entity.metadata.name}\n </Typography>\n </Grid>\n <Grid item xs={4}>\n <img\n src={EmptyStateImage}\n alt=\"EmptyState\"\n data-testid=\"emptyStateImg\"\n />\n </Grid>\n </Grid>\n )}\n {kubernetesObjects?.items.length > 0 &&\n kubernetesObjects?.items.map((item, i) => {\n const podsWithErrors = new Set<string>(\n detectedErrors\n .get(item.cluster.name)\n ?.filter(de => de.kind === 'Pod')\n .map(de => de.names)\n .flat() ?? [],\n );\n\n return (\n <Grid item key={i} xs={12}>\n <Cluster\n clusterObjects={item}\n podsWithErrors={podsWithErrors}\n />\n </Grid>\n );\n })}\n </Grid>\n </Grid>\n )}\n </Content>\n </Page>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { Entity } from '@backstage/catalog-model';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { Route, Routes } from 'react-router-dom';\nimport { rootCatalogKubernetesRouteRef } from './plugin';\nimport { KubernetesContent } from './components/KubernetesContent';\nimport { Button } from '@material-ui/core';\nimport { MissingAnnotationEmptyState } from '@backstage/core-components';\n\nconst KUBERNETES_ANNOTATION = 'backstage.io/kubernetes-id';\nconst KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION =\n 'backstage.io/kubernetes-label-selector';\n\ntype Props = {\n /** @deprecated The entity is now grabbed from context instead */\n entity?: Entity;\n};\n\nexport const Router = (_props: Props) => {\n const { entity } = useEntity();\n\n const kubernetesAnnotationValue =\n entity.metadata.annotations?.[KUBERNETES_ANNOTATION];\n\n const kubernetesLabelSelectorQueryAnnotationValue =\n entity.metadata.annotations?.[KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION];\n\n if (\n kubernetesAnnotationValue ||\n kubernetesLabelSelectorQueryAnnotationValue\n ) {\n return (\n <Routes>\n <Route\n path={`/${rootCatalogKubernetesRouteRef.path}`}\n element={<KubernetesContent entity={entity} />}\n />\n </Routes>\n );\n }\n\n return (\n <>\n <MissingAnnotationEmptyState annotation={KUBERNETES_ANNOTATION} />\n <h1>\n Or use a label selector query, which takes precedence over the previous\n annotation.\n </h1>\n <Button\n variant=\"contained\"\n color=\"primary\"\n href=\"https://backstage.io/docs/features/kubernetes/configuration#surfacing-your-kubernetes-components-as-part-of-an-entity\"\n >\n Read Kubernetes Plugin Docs\n </Button>\n </>\n );\n};\n"],"names":["columns","React"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/api/KubernetesBackendClient.ts","../src/api/types.ts","../src/kubernetes-auth-provider/types.ts","../src/kubernetes-auth-provider/GoogleKubernetesAuthProvider.ts","../src/kubernetes-auth-provider/ServiceAccountKubernetesAuthProvider.ts","../src/kubernetes-auth-provider/AwsKubernetesAuthProvider.ts","../src/kubernetes-auth-provider/KubernetesAuthProviders.ts","../src/plugin.ts","../src/components/KubernetesContent/ErrorPanel.tsx","../src/utils/pod.tsx","../src/components/KubernetesDrawer/KubernetesDrawer.tsx","../src/components/Pods/PodDrawer.tsx","../src/components/Pods/PodsTable.tsx","../src/components/DeploymentsAccordions/DeploymentDrawer.tsx","../src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.tsx","../src/utils/owner.ts","../src/hooks/useKubernetesObjects.ts","../src/hooks/PodNamesWithErrors.ts","../src/hooks/GroupedResponses.ts","../src/components/DeploymentsAccordions/DeploymentsAccordions.tsx","../src/components/ErrorReporting/ErrorReporting.tsx","../src/utils/response.ts","../src/error-detection/common.ts","../src/error-detection/pods.ts","../src/error-detection/deployments.ts","../src/error-detection/hpas.ts","../src/error-detection/error-detection.ts","../src/components/IngressesAccordions/IngressDrawer.tsx","../src/components/IngressesAccordions/IngressesAccordions.tsx","../src/components/ServicesAccordions/ServiceDrawer.tsx","../src/components/ServicesAccordions/ServicesAccordions.tsx","../src/components/CustomResources/ArgoRollouts/RolloutDrawer.tsx","../src/components/CustomResources/ArgoRollouts/StepsProgress.tsx","../src/components/CustomResources/ArgoRollouts/Rollout.tsx","../src/components/CustomResources/DefaultCustomResourceDrawer.tsx","../src/components/CustomResources/DefaultCustomResource.tsx","../src/components/CustomResources/CustomResources.tsx","../src/components/KubernetesContent/KubernetesContent.tsx","../src/Router.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesApi } from './types';\nimport {\n KubernetesRequestBody,\n ObjectsByEntityResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';\n\nexport class KubernetesBackendClient implements KubernetesApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly identityApi: IdentityApi;\n\n constructor(options: {\n discoveryApi: DiscoveryApi;\n identityApi: IdentityApi;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.identityApi = options.identityApi;\n }\n\n private async handleResponse(response: Response): Promise<any> {\n if (!response.ok) {\n const payload = await response.text();\n let message;\n switch (response.status) {\n case 404:\n message =\n 'Could not find the Kubernetes Backend (HTTP 404). Make sure the plugin has been fully installed.';\n break;\n default:\n message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;\n }\n throw new Error(message);\n }\n\n return await response.json();\n }\n\n private async postRequired(\n path: string,\n requestBody: KubernetesRequestBody,\n ): Promise<any> {\n const url = `${await this.discoveryApi.getBaseUrl('kubernetes')}${path}`;\n const idToken = await this.identityApi.getIdToken();\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(idToken && { Authorization: `Bearer ${idToken}` }),\n },\n body: JSON.stringify(requestBody),\n });\n\n return this.handleResponse(response);\n }\n\n async getObjectsByEntity(\n requestBody: KubernetesRequestBody,\n ): Promise<ObjectsByEntityResponse> {\n return await this.postRequired(\n `/services/${requestBody.entity.metadata.name}`,\n requestBody,\n );\n }\n\n async getClusters(): Promise<{ name: string; authProvider: string }[]> {\n const url = `${await this.discoveryApi.getBaseUrl('kubernetes')}/clusters`;\n\n const response = await fetch(url, {\n method: 'GET',\n });\n\n return (await this.handleResponse(response)).items;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n KubernetesRequestBody,\n ObjectsByEntityResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\nexport const kubernetesApiRef = createApiRef<KubernetesApi>({\n id: 'plugin.kubernetes.service',\n description:\n 'Used by the Kubernetes plugin to make requests to accompanying backend',\n});\n\nexport interface KubernetesApi {\n getObjectsByEntity(\n requestBody: KubernetesRequestBody,\n ): Promise<ObjectsByEntityResponse>;\n getClusters(): Promise<{ name: string; authProvider: string }[]>;\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\nexport interface KubernetesAuthProvider {\n decorateRequestBodyForAuth(\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody>;\n}\n\nexport const kubernetesAuthProvidersApiRef =\n createApiRef<KubernetesAuthProvidersApi>({\n id: 'plugin.kubernetes-auth-providers.service',\n description:\n 'Used by the Kubernetes plugin to fetch KubernetesAuthProviders',\n });\n\nexport interface KubernetesAuthProvidersApi {\n decorateRequestBodyForAuth(\n authProvider: string,\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody>;\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthProvider } from './types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\nimport { OAuthApi } from '@backstage/core-plugin-api';\n\nexport class GoogleKubernetesAuthProvider implements KubernetesAuthProvider {\n authProvider: OAuthApi;\n\n constructor(authProvider: OAuthApi) {\n this.authProvider = authProvider;\n }\n\n async decorateRequestBodyForAuth(\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody> {\n const googleAuthToken: string = await this.authProvider.getAccessToken(\n 'https://www.googleapis.com/auth/cloud-platform',\n );\n if ('auth' in requestBody) {\n requestBody.auth!.google = googleAuthToken;\n } else {\n requestBody.auth = { google: googleAuthToken };\n }\n return requestBody;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthProvider } from './types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class ServiceAccountKubernetesAuthProvider\n implements KubernetesAuthProvider\n{\n async decorateRequestBodyForAuth(\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody> {\n // No-op, with service account for auth, cluster config/details should already have serviceAccountToken\n return requestBody;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthProvider } from './types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class AwsKubernetesAuthProvider implements KubernetesAuthProvider {\n async decorateRequestBodyForAuth(\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody> {\n // No-op, with aws auth, server's AWS credentials are used for access\n return requestBody;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\nimport { KubernetesAuthProvider, KubernetesAuthProvidersApi } from './types';\nimport { GoogleKubernetesAuthProvider } from './GoogleKubernetesAuthProvider';\nimport { ServiceAccountKubernetesAuthProvider } from './ServiceAccountKubernetesAuthProvider';\nimport { AwsKubernetesAuthProvider } from './AwsKubernetesAuthProvider';\nimport { OAuthApi } from '@backstage/core-plugin-api';\n\nexport class KubernetesAuthProviders implements KubernetesAuthProvidersApi {\n private readonly kubernetesAuthProviderMap: Map<\n string,\n KubernetesAuthProvider\n >;\n\n constructor(options: { googleAuthApi: OAuthApi }) {\n this.kubernetesAuthProviderMap = new Map<string, KubernetesAuthProvider>();\n this.kubernetesAuthProviderMap.set(\n 'google',\n new GoogleKubernetesAuthProvider(options.googleAuthApi),\n );\n this.kubernetesAuthProviderMap.set(\n 'serviceAccount',\n new ServiceAccountKubernetesAuthProvider(),\n );\n this.kubernetesAuthProviderMap.set('aws', new AwsKubernetesAuthProvider());\n }\n\n async decorateRequestBodyForAuth(\n authProvider: string,\n requestBody: KubernetesRequestBody,\n ): Promise<KubernetesRequestBody> {\n const kubernetesAuthProvider: KubernetesAuthProvider | undefined =\n this.kubernetesAuthProviderMap.get(authProvider);\n if (kubernetesAuthProvider) {\n return await kubernetesAuthProvider.decorateRequestBodyForAuth(\n requestBody,\n );\n }\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthProvider defined for it`,\n );\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesBackendClient } from './api/KubernetesBackendClient';\nimport { kubernetesApiRef } from './api/types';\nimport { kubernetesAuthProvidersApiRef } from './kubernetes-auth-provider/types';\nimport { KubernetesAuthProviders } from './kubernetes-auth-provider/KubernetesAuthProviders';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n discoveryApiRef,\n identityApiRef,\n googleAuthApiRef,\n createRoutableExtension,\n} from '@backstage/core-plugin-api';\n\nexport const rootCatalogKubernetesRouteRef = createRouteRef({\n path: '*',\n title: 'Kubernetes',\n});\n\nexport const kubernetesPlugin = createPlugin({\n id: 'kubernetes',\n apis: [\n createApiFactory({\n api: kubernetesApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ discoveryApi, identityApi }) =>\n new KubernetesBackendClient({ discoveryApi, identityApi }),\n }),\n createApiFactory({\n api: kubernetesAuthProvidersApiRef,\n deps: { googleAuthApi: googleAuthApiRef },\n factory: ({ googleAuthApi }) => {\n return new KubernetesAuthProviders({ googleAuthApi });\n },\n }),\n ],\n routes: {\n entityContent: rootCatalogKubernetesRouteRef,\n },\n});\n\nexport const EntityKubernetesContent = kubernetesPlugin.provide(\n createRoutableExtension({\n component: () => import('./Router').then(m => m.Router),\n mountPoint: rootCatalogKubernetesRouteRef,\n }),\n);\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { Typography } from '@material-ui/core';\nimport { ClusterObjects } from '@backstage/plugin-kubernetes-common';\nimport { WarningPanel } from '@backstage/core-components';\n\nconst clustersWithErrorsToErrorMessage = (\n clustersWithErrors: ClusterObjects[],\n): React.ReactNode => {\n return clustersWithErrors.map((c, i) => {\n return (\n <div key={i}>\n <Typography variant=\"body2\">{`Cluster: ${c.cluster.name}`}</Typography>\n {c.errors.map((e, j) => {\n return (\n <Typography variant=\"body2\" key={j}>\n {`Error fetching Kubernetes resource: '${e.resourcePath}', error: ${e.errorType}, status code: ${e.statusCode}`}\n </Typography>\n );\n })}\n <br />\n </div>\n );\n });\n};\n\ntype ErrorPanelProps = {\n entityName: string;\n errorMessage?: string;\n clustersWithErrors?: ClusterObjects[];\n children?: React.ReactNode;\n};\n\nexport const ErrorPanel = ({\n entityName,\n errorMessage,\n clustersWithErrors,\n}: ErrorPanelProps) => (\n <WarningPanel\n title=\"There was a problem retrieving Kubernetes objects\"\n 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.`}\n >\n {clustersWithErrors && (\n <div>Errors: {clustersWithErrorsToErrorMessage(clustersWithErrors)}</div>\n )}\n {errorMessage && (\n <Typography variant=\"body2\">Errors: {errorMessage}</Typography>\n )}\n </WarningPanel>\n);\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { V1Pod, V1PodCondition } from '@kubernetes/client-node';\nimport React, { Fragment, ReactNode } from 'react';\nimport { Chip } from '@material-ui/core';\nimport { V1DeploymentCondition } from '@kubernetes/client-node/dist/gen/model/v1DeploymentCondition';\nimport {\n StatusAborted,\n StatusError,\n StatusOK,\n SubvalueCell,\n} from '@backstage/core-components';\n\nexport const imageChips = (pod: V1Pod): ReactNode => {\n const containerStatuses = pod.status?.containerStatuses ?? [];\n const images = containerStatuses.map((cs, i) => {\n return <Chip key={i} label={`${cs.name}=${cs.image}`} size=\"small\" />;\n });\n\n return <div>{images}</div>;\n};\n\nexport const containersReady = (pod: V1Pod): string => {\n const containerStatuses = pod.status?.containerStatuses ?? [];\n const containersReadyItem = containerStatuses.filter(cs => cs.ready).length;\n\n return `${containersReadyItem}/${containerStatuses.length}`;\n};\n\nexport const totalRestarts = (pod: V1Pod): number => {\n const containerStatuses = pod.status?.containerStatuses ?? [];\n return containerStatuses?.reduce((a, b) => a + b.restartCount, 0);\n};\n\nexport const containerStatuses = (pod: V1Pod): ReactNode => {\n const containerStatusesItem = pod.status?.containerStatuses ?? [];\n const errors = containerStatusesItem.reduce((accum, next) => {\n if (next.state === undefined) {\n return accum;\n }\n\n const waiting = next.state.waiting;\n const terminated = next.state.terminated;\n\n const renderCell = (reason: string | undefined) => (\n <Fragment key={`${pod.metadata?.name}-${next.name}`}>\n <SubvalueCell\n value={<StatusError>Container: {next.name}</StatusError>}\n subvalue={reason}\n />\n <br />\n </Fragment>\n );\n\n if (waiting) {\n accum.push(renderCell(waiting.reason));\n }\n\n if (terminated) {\n accum.push(renderCell(terminated.reason));\n }\n\n return accum;\n }, [] as React.ReactNode[]);\n\n if (errors.length === 0) {\n return <StatusOK>OK</StatusOK>;\n }\n\n return errors;\n};\n\nexport const renderCondition = (\n condition: V1PodCondition | V1DeploymentCondition,\n): [string, ReactNode] => {\n const status = condition.status;\n\n if (status === 'True') {\n return [condition.type, <StatusOK>True</StatusOK>];\n } else if (status === 'False') {\n return [\n condition.type,\n <SubvalueCell\n value={<StatusError>False</StatusError>}\n subvalue={condition.message ?? ''}\n />,\n ];\n }\n return [condition.type, <StatusAborted />];\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { ChangeEvent, useState } from 'react';\nimport {\n Button,\n Typography,\n makeStyles,\n IconButton,\n createStyles,\n Theme,\n Drawer,\n Switch,\n FormControlLabel,\n Grid,\n} from '@material-ui/core';\nimport Close from '@material-ui/icons/Close';\nimport { V1ObjectMeta } from '@kubernetes/client-node';\nimport { withStyles } from '@material-ui/core/styles';\nimport jsYaml from 'js-yaml';\nimport {\n CodeSnippet,\n StructuredMetadataTable,\n} from '@backstage/core-components';\n\nconst useDrawerStyles = makeStyles((theme: Theme) =>\n createStyles({\n paper: {\n width: '50%',\n justifyContent: 'space-between',\n padding: theme.spacing(2.5),\n },\n }),\n);\n\nconst useDrawerContentStyles = makeStyles((_: Theme) =>\n createStyles({\n header: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'space-between',\n },\n options: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'flex-end',\n },\n icon: {\n fontSize: 20,\n },\n content: {\n height: '80%',\n },\n }),\n);\n\nconst PodDrawerButton = withStyles({\n root: {\n padding: '6px 5px',\n },\n label: {\n textTransform: 'none',\n },\n})(Button);\n\ninterface KubernetesDrawerable {\n metadata?: V1ObjectMeta;\n}\n\ninterface KubernetesDrawerContentProps<T extends KubernetesDrawerable> {\n toggleDrawer: (e: ChangeEvent<{}>, isOpen: boolean) => void;\n object: T;\n renderObject: (obj: T) => object;\n kind: string;\n}\n\nfunction replaceNullsWithUndefined(someObj: any) {\n const replacer = (_: any, value: any) =>\n String(value) === 'null' || String(value) === 'undefined'\n ? undefined\n : value;\n\n return JSON.parse(JSON.stringify(someObj, replacer));\n}\n\nconst KubernetesDrawerContent = <T extends KubernetesDrawerable>({\n toggleDrawer,\n object,\n renderObject,\n kind,\n}: KubernetesDrawerContentProps<T>) => {\n const [isYaml, setIsYaml] = useState<boolean>(false);\n\n const classes = useDrawerContentStyles();\n\n return (\n <>\n <div className={classes.header}>\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid item>\n <Typography variant=\"h5\">\n {object.metadata?.name ?? 'unknown name'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n {kind}\n </Typography>\n </Grid>\n </Grid>\n <IconButton\n key=\"dismiss\"\n title=\"Close the drawer\"\n onClick={e => toggleDrawer(e, false)}\n color=\"inherit\"\n >\n <Close className={classes.icon} />\n </IconButton>\n </div>\n <div className={classes.options}>\n <FormControlLabel\n control={\n <Switch\n checked={isYaml}\n onChange={event => {\n setIsYaml(event.target.checked);\n }}\n name=\"YAML\"\n />\n }\n label=\"YAML\"\n />\n </div>\n <div className={classes.content}>\n {isYaml && <CodeSnippet language=\"yaml\" text={jsYaml.dump(object)} />}\n {!isYaml && (\n <StructuredMetadataTable\n metadata={renderObject(replaceNullsWithUndefined(object))}\n />\n )}\n </div>\n </>\n );\n};\ninterface KubernetesDrawerProps<T extends KubernetesDrawerable> {\n object: T;\n renderObject: (obj: T) => object;\n buttonVariant?: 'h5' | 'subtitle2';\n kind: string;\n expanded?: boolean;\n children?: React.ReactNode;\n}\n\nexport const KubernetesDrawer = <T extends KubernetesDrawerable>({\n object,\n renderObject,\n kind,\n buttonVariant = 'subtitle2',\n expanded = false,\n children,\n}: KubernetesDrawerProps<T>) => {\n const [isOpen, setIsOpen] = useState(expanded);\n const classes = useDrawerStyles();\n\n const toggleDrawer = (e: ChangeEvent<{}>, newValue: boolean) => {\n e.stopPropagation();\n setIsOpen(newValue);\n };\n\n return (\n <>\n <PodDrawerButton\n onClick={e => toggleDrawer(e, true)}\n onFocus={event => event.stopPropagation()}\n >\n {children === undefined ? (\n <Typography variant={buttonVariant}>\n {object.metadata?.name ?? 'unknown object'}\n </Typography>\n ) : (\n children\n )}\n </PodDrawerButton>\n <Drawer\n classes={{\n paper: classes.paper,\n }}\n anchor=\"right\"\n open={isOpen}\n onClose={(e: any) => toggleDrawer(e, false)}\n onClick={event => event.stopPropagation()}\n >\n <KubernetesDrawerContent\n kind={kind}\n toggleDrawer={toggleDrawer}\n object={object}\n renderObject={renderObject}\n />\n </Drawer>\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1Pod } from '@kubernetes/client-node';\nimport {\n containersReady,\n containerStatuses,\n totalRestarts,\n imageChips,\n renderCondition,\n} from '../../utils/pod';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\n\nexport const PodDrawer = ({\n pod,\n expanded,\n}: {\n pod: V1Pod;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={pod}\n expanded={expanded}\n kind=\"Pod\"\n renderObject={(podObject: V1Pod) => {\n const phase = podObject.status?.phase ?? 'unknown';\n\n const ports =\n podObject.spec?.containers?.map(c => {\n return {\n [c.name]: c.ports,\n };\n }) ?? 'N/A';\n\n const conditions = (podObject.status?.conditions ?? [])\n .map(renderCondition)\n .reduce((accum, next) => {\n accum[next[0]] = next[1];\n return accum;\n }, {} as { [key: string]: React.ReactNode });\n\n return {\n images: imageChips(podObject),\n phase: phase,\n 'Containers Ready': containersReady(podObject),\n 'Total Restarts': totalRestarts(podObject),\n 'Container Statuses': containerStatuses(podObject),\n ...conditions,\n 'Exposed ports': ports,\n };\n }}\n />\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1Pod } from '@kubernetes/client-node';\nimport { PodDrawer } from './PodDrawer';\nimport {\n containersReady,\n containerStatuses,\n totalRestarts,\n} from '../../utils/pod';\nimport { Table, TableColumn } from '@backstage/core-components';\n\nconst columns: TableColumn<V1Pod>[] = [\n {\n title: 'name',\n highlight: true,\n render: (pod: V1Pod) => <PodDrawer pod={pod} />,\n },\n {\n title: 'phase',\n render: (pod: V1Pod) => pod.status?.phase ?? 'unknown',\n },\n {\n title: 'containers ready',\n align: 'center',\n render: containersReady,\n },\n {\n title: 'total restarts',\n align: 'center',\n render: totalRestarts,\n type: 'numeric',\n },\n {\n title: 'status',\n render: containerStatuses,\n },\n];\n\ntype DeploymentTablesProps = {\n pods: V1Pod[];\n children?: React.ReactNode;\n};\n\nexport const PodsTable = ({ pods }: DeploymentTablesProps) => {\n const tableStyle = {\n minWidth: '0',\n width: '100%',\n };\n\n return (\n <div style={tableStyle}>\n <Table\n options={{ paging: true, search: false }}\n data={pods}\n columns={columns}\n />\n </div>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1Deployment } from '@kubernetes/client-node';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\nimport { renderCondition } from '../../utils/pod';\nimport { Typography, Grid } from '@material-ui/core';\n\nexport const DeploymentDrawer = ({\n deployment,\n expanded,\n}: {\n deployment: V1Deployment;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={deployment}\n expanded={expanded}\n kind=\"Deployment\"\n renderObject={(deploymentObj: V1Deployment) => {\n const conditions = (deploymentObj.status?.conditions ?? [])\n .map(renderCondition)\n .reduce((accum, next) => {\n accum[next[0]] = next[1];\n return accum;\n }, {} as { [key: string]: React.ReactNode });\n\n return {\n strategy: deploymentObj.spec?.strategy ?? '???',\n minReadySeconds: deploymentObj.spec?.minReadySeconds ?? '???',\n progressDeadlineSeconds:\n deploymentObj.spec?.progressDeadlineSeconds ?? '???',\n ...conditions,\n };\n }}\n >\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {deployment.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Deployment\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1HorizontalPodAutoscaler } from '@kubernetes/client-node';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\n\nexport const HorizontalPodAutoscalerDrawer = ({\n hpa,\n expanded,\n children,\n}: {\n hpa: V1HorizontalPodAutoscaler;\n expanded?: boolean;\n children?: React.ReactNode;\n}) => {\n return (\n <KubernetesDrawer\n kind=\"HorizontalPodAutoscaler\"\n object={hpa}\n expanded={expanded}\n renderObject={(hpaObject: V1HorizontalPodAutoscaler) => {\n return {\n targetCPUUtilizationPercentage:\n hpaObject.spec?.targetCPUUtilizationPercentage,\n currentCPUUtilizationPercentage:\n hpaObject.status?.currentCPUUtilizationPercentage,\n minReplicas: hpaObject.spec?.minReplicas,\n maxReplicas: hpaObject.spec?.maxReplicas,\n currentReplicas: hpaObject.status?.currentReplicas,\n desiredReplicas: hpaObject.status?.desiredReplicas,\n };\n }}\n >\n {children}\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { V1ObjectMeta } from '@kubernetes/client-node/dist/gen/model/v1ObjectMeta';\nimport {\n V1HorizontalPodAutoscaler,\n V1Pod,\n V1ReplicaSet,\n} from '@kubernetes/client-node';\n\ninterface CanOwn {\n metadata?: V1ObjectMeta;\n}\n\ninterface CanBeOwned {\n metadata?: V1ObjectMeta;\n}\n\nexport function getOwnedResources<R extends CanBeOwned>(\n potentialOwner: CanOwn,\n possiblyOwned: R[],\n): R[] {\n return possiblyOwned.filter(\n p =>\n p.metadata?.ownerReferences?.some(\n o => o.uid === potentialOwner.metadata?.uid,\n ) ?? false,\n );\n}\n\nexport const getOwnedPodsThroughReplicaSets = (\n potentialOwner: CanOwn,\n replicaSets: V1ReplicaSet[],\n pods: V1Pod[],\n) => {\n return getOwnedResources(\n potentialOwner,\n replicaSets.filter(rs => rs.status && rs.status.replicas > 0),\n ).reduce((accum, rs) => {\n return accum.concat(getOwnedResources(rs, pods));\n }, [] as V1Pod[]);\n};\n\nexport const getMatchingHpa = (\n ownerName: string | undefined,\n ownerKind: string,\n hpas: V1HorizontalPodAutoscaler[],\n): V1HorizontalPodAutoscaler | undefined => {\n return hpas.find(hpa => {\n return (\n (hpa.spec?.scaleTargetRef?.kind ?? '').toLowerCase() ===\n ownerKind.toLowerCase() &&\n (hpa.spec?.scaleTargetRef?.name ?? '') ===\n (ownerName ?? 'unknown-deployment')\n );\n });\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { kubernetesApiRef } from '../api/types';\nimport { kubernetesAuthProvidersApiRef } from '../kubernetes-auth-provider/types';\nimport { useEffect, useState } from 'react';\nimport {\n KubernetesRequestBody,\n ObjectsByEntityResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport { useApi } from '@backstage/core-plugin-api';\n\nexport interface KubernetesObjects {\n kubernetesObjects: ObjectsByEntityResponse | undefined;\n error: string | undefined;\n}\n\nexport const useKubernetesObjects = (entity: Entity): KubernetesObjects => {\n const kubernetesApi = useApi(kubernetesApiRef);\n const kubernetesAuthProvidersApi = useApi(kubernetesAuthProvidersApiRef);\n const [kubernetesObjects, setKubernetesObjects] = useState<\n ObjectsByEntityResponse | undefined\n >(undefined);\n\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n (async () => {\n let clusters = [];\n\n try {\n clusters = await kubernetesApi.getClusters();\n } catch (e) {\n setError(e.message);\n return;\n }\n\n const authProviders: string[] = [\n ...new Set(clusters.map(c => c.authProvider)),\n ];\n // For each auth type, invoke decorateRequestBodyForAuth on corresponding KubernetesAuthProvider\n let requestBody: KubernetesRequestBody = {\n entity,\n };\n for (const authProviderStr of authProviders) {\n // Multiple asyncs done sequentially instead of all at once to prevent same requestBody from being modified simultaneously\n try {\n requestBody =\n await kubernetesAuthProvidersApi.decorateRequestBodyForAuth(\n authProviderStr,\n requestBody,\n );\n } catch (e) {\n setError(e.message);\n return;\n }\n }\n\n try {\n setKubernetesObjects(\n await kubernetesApi.getObjectsByEntity(requestBody),\n );\n } catch (e) {\n setError(e.message);\n return;\n }\n })();\n /* eslint-disable react-hooks/exhaustive-deps */\n }, [entity.metadata.name, kubernetesApi, kubernetesAuthProvidersApi]);\n /* eslint-enable react-hooks/exhaustive-deps */\n\n return {\n kubernetesObjects,\n error,\n };\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nexport const PodNamesWithErrorsContext = React.createContext<Set<string>>(\n new Set<string>(),\n);\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport { GroupedResponses } from '../types/types';\n\nexport const GroupedResponsesContext = React.createContext<GroupedResponses>({\n pods: [],\n replicaSets: [],\n deployments: [],\n services: [],\n configMaps: [],\n horizontalPodAutoscalers: [],\n ingresses: [],\n customResources: [],\n});\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport {\n V1Deployment,\n V1Pod,\n V1HorizontalPodAutoscaler,\n} from '@kubernetes/client-node';\nimport { PodsTable } from '../Pods';\nimport { DeploymentDrawer } from './DeploymentDrawer';\nimport { HorizontalPodAutoscalerDrawer } from '../HorizontalPodAutoscalers';\nimport {\n getOwnedPodsThroughReplicaSets,\n getMatchingHpa,\n} from '../../utils/owner';\nimport {\n GroupedResponsesContext,\n PodNamesWithErrorsContext,\n} from '../../hooks';\nimport { StatusError, StatusOK } from '@backstage/core-components';\n\ntype DeploymentsAccordionsProps = {\n children?: React.ReactNode;\n};\n\ntype DeploymentAccordionProps = {\n deployment: V1Deployment;\n ownedPods: V1Pod[];\n matchingHpa?: V1HorizontalPodAutoscaler;\n children?: React.ReactNode;\n};\n\ntype DeploymentSummaryProps = {\n deployment: V1Deployment;\n numberOfCurrentPods: number;\n numberOfPodsWithErrors: number;\n hpa?: V1HorizontalPodAutoscaler;\n children?: React.ReactNode;\n};\n\nconst DeploymentSummary = ({\n deployment,\n numberOfCurrentPods,\n numberOfPodsWithErrors,\n hpa,\n}: DeploymentSummaryProps) => {\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"flex-start\"\n alignItems=\"center\"\n >\n <Grid xs={3} item>\n <DeploymentDrawer deployment={deployment} />\n </Grid>\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n {hpa && (\n <Grid item xs={3}>\n <HorizontalPodAutoscalerDrawer hpa={hpa}>\n <Grid\n item\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"subtitle2\">\n min replicas {hpa.spec?.minReplicas ?? '?'} / max replicas{' '}\n {hpa.spec?.maxReplicas ?? '?'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography variant=\"subtitle2\">\n current CPU usage:{' '}\n {hpa.status?.currentCPUUtilizationPercentage ?? '?'}%\n </Typography>\n </Grid>\n <Grid item>\n <Typography variant=\"subtitle2\">\n target CPU usage:{' '}\n {hpa.spec?.targetCPUUtilizationPercentage ?? '?'}%\n </Typography>\n </Grid>\n </Grid>\n </HorizontalPodAutoscalerDrawer>\n </Grid>\n )}\n <Grid\n item\n container\n xs={3}\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid item>\n <StatusOK>{numberOfCurrentPods} pods</StatusOK>\n </Grid>\n <Grid item>\n {numberOfPodsWithErrors > 0 ? (\n <StatusError>\n {numberOfPodsWithErrors} pod\n {numberOfPodsWithErrors > 1 ? 's' : ''} with errors\n </StatusError>\n ) : (\n <StatusOK>No pods with errors</StatusOK>\n )}\n </Grid>\n </Grid>\n </Grid>\n );\n};\n\nconst DeploymentAccordion = ({\n deployment,\n ownedPods,\n matchingHpa,\n}: DeploymentAccordionProps) => {\n const podNamesWithErrors = useContext(PodNamesWithErrorsContext);\n\n const podsWithErrors = ownedPods.filter(p =>\n podNamesWithErrors.has(p.metadata?.name ?? ''),\n );\n\n return (\n <Accordion TransitionProps={{ unmountOnExit: true }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <DeploymentSummary\n deployment={deployment}\n numberOfCurrentPods={ownedPods.length}\n numberOfPodsWithErrors={podsWithErrors.length}\n hpa={matchingHpa}\n />\n </AccordionSummary>\n <AccordionDetails>\n <PodsTable pods={ownedPods} />\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport const DeploymentsAccordions = ({}: DeploymentsAccordionsProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n\n return (\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {groupedResponses.deployments.map((deployment, i) => (\n <Grid container item key={i} xs>\n <Grid item xs>\n <DeploymentAccordion\n matchingHpa={getMatchingHpa(\n deployment.metadata?.name,\n 'deployment',\n groupedResponses.horizontalPodAutoscalers,\n )}\n ownedPods={getOwnedPodsThroughReplicaSets(\n deployment,\n groupedResponses.replicaSets,\n groupedResponses.pods,\n )}\n deployment={deployment}\n />\n </Grid>\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport * as React from 'react';\nimport { DetectedError, DetectedErrorsByCluster } from '../../error-detection';\nimport { Chip, Typography, Grid } from '@material-ui/core';\nimport EmptyStateImage from '../../assets/emptystate.svg';\nimport { Table, TableColumn, InfoCard } from '@backstage/core-components';\n\ntype ErrorReportingProps = {\n detectedErrors: DetectedErrorsByCluster;\n};\n\nconst columns: TableColumn<DetectedError>[] = [\n {\n title: 'cluster',\n width: '15%',\n render: (detectedError: DetectedError) => detectedError.cluster,\n },\n {\n title: 'kind',\n width: '15%',\n render: (detectedError: DetectedError) => detectedError.kind,\n },\n {\n title: 'name',\n width: '30%',\n render: (detectedError: DetectedError) => {\n const errorCount = detectedError.names.length;\n\n if (errorCount === 0) {\n // This shouldn't happen\n return null;\n }\n\n const displayName = detectedError.names[0];\n\n const otherErrorCount = errorCount - 1;\n\n return (\n <>\n {displayName}{' '}\n {otherErrorCount > 0 && (\n <Chip\n label={`+ ${otherErrorCount} other${\n otherErrorCount > 1 ? 's' : ''\n }`}\n size=\"small\"\n />\n )}\n </>\n );\n },\n },\n {\n title: 'messages',\n width: '40%',\n render: (detectedError: DetectedError) => (\n <>\n {detectedError.message.map((m, i) => (\n <div key={i}>{m}</div>\n ))}\n </>\n ),\n },\n];\n\nconst sortBySeverity = (a: DetectedError, b: DetectedError) => {\n if (a.severity < b.severity) {\n return 1;\n } else if (b.severity < a.severity) {\n return -1;\n }\n return 0;\n};\n\nexport const ErrorEmptyState = () => {\n return (\n <Grid\n container\n justifyContent=\"space-around\"\n direction=\"row\"\n alignItems=\"center\"\n spacing={2}\n >\n <Grid item xs={4}>\n <Typography variant=\"h5\">\n Nice! There are no errors to report!\n </Typography>\n </Grid>\n <Grid item xs={4}>\n <img\n src={EmptyStateImage}\n alt=\"EmptyState\"\n data-testid=\"emptyStateImg\"\n />\n </Grid>\n </Grid>\n );\n};\n\nexport const ErrorReporting = ({ detectedErrors }: ErrorReportingProps) => {\n const errors = Array.from(detectedErrors.values())\n .flat()\n .sort(sortBySeverity);\n\n return (\n <>\n {errors.length === 0 ? (\n <InfoCard title=\"Error Reporting\">\n <ErrorEmptyState />\n </InfoCard>\n ) : (\n <Table\n title=\"Error Reporting\"\n data={errors}\n columns={columns}\n options={{ paging: true, search: false }}\n />\n )}\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FetchResponse } from '@backstage/plugin-kubernetes-common';\nimport { GroupedResponses } from '../types/types';\n\n// TODO this could probably be a lodash groupBy\nexport const groupResponses = (\n fetchResponse: FetchResponse[],\n): GroupedResponses => {\n return fetchResponse.reduce(\n (prev, next) => {\n switch (next.type) {\n case 'deployments':\n prev.deployments.push(...next.resources);\n break;\n case 'pods':\n prev.pods.push(...next.resources);\n break;\n case 'replicasets':\n prev.replicaSets.push(...next.resources);\n break;\n case 'services':\n prev.services.push(...next.resources);\n break;\n case 'configmaps':\n prev.configMaps.push(...next.resources);\n break;\n case 'horizontalpodautoscalers':\n prev.horizontalPodAutoscalers.push(...next.resources);\n break;\n case 'ingresses':\n prev.ingresses.push(...next.resources);\n break;\n case 'customresources':\n prev.customResources.push(...next.resources);\n break;\n default:\n }\n return prev;\n },\n {\n pods: [],\n replicaSets: [],\n deployments: [],\n services: [],\n configMaps: [],\n horizontalPodAutoscalers: [],\n ingresses: [],\n customResources: [],\n } as GroupedResponses,\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DetectedError,\n ErrorDetectable,\n ErrorDetectableKind,\n ErrorMapper,\n} from './types';\n\n// Run through the each error mapper for each object\n// returning a deduplicated (mostly) result\nexport const detectErrorsInObjects = <T extends ErrorDetectable>(\n objects: T[],\n kind: ErrorDetectableKind,\n clusterName: string,\n errorMappers: ErrorMapper<T>[],\n): DetectedError[] => {\n // Build up a map of errors\n // key: the joined message produced by an error\n // value: the error\n const errors = new Map<string, DetectedError>();\n\n for (const object of objects) {\n for (const errorMapper of errorMappers) {\n if (errorMapper.errorExists(object)) {\n const message = errorMapper.messageAccessor(object);\n\n // TODO This is not perfect as errors with uuid/hashes/date/times will not be caught by this\n const dedupKey = message.join('');\n\n const value = errors.get(dedupKey);\n\n const name = object.metadata?.name ?? 'unknown';\n\n if (value !== undefined) {\n // This gets translated into the Chip \"+5 others\"\n // in the ErrorReporting component\n // but we need to keep the names so we can easily\n // find which objects owns the error later\n value.names.push(name);\n errors.set(dedupKey, value);\n } else {\n errors.set(dedupKey, {\n cluster: clusterName,\n kind: kind,\n names: [name],\n message: message,\n severity: errorMapper.severity,\n });\n }\n }\n }\n }\n\n return Array.from(errors.values());\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { V1Pod } from '@kubernetes/client-node';\nimport { totalRestarts } from '../utils/pod';\nimport { DetectedError, ErrorMapper } from './types';\nimport { detectErrorsInObjects } from './common';\n\nconst podErrorMappers: ErrorMapper<V1Pod>[] = [\n {\n severity: 5,\n errorExplanation: 'status-message',\n errorExists: pod => {\n return pod.status?.message !== undefined;\n },\n messageAccessor: pod => {\n return [pod.status?.message ?? ''];\n },\n },\n {\n severity: 4,\n errorExplanation: 'containers-restarting',\n errorExists: pod => {\n // TODO magic number\n return totalRestarts(pod) > 3;\n },\n messageAccessor: pod => {\n return (pod.status?.containerStatuses ?? [])\n .filter(cs => cs.restartCount > 0)\n .map(cs => `container=${cs.name} restarted ${cs.restartCount} times`);\n },\n },\n {\n severity: 5,\n errorExplanation: 'condition-message-present',\n errorExists: pod => {\n return (pod.status?.conditions ?? []).some(c => c.message !== undefined);\n },\n messageAccessor: pod => {\n return (pod.status?.conditions ?? [])\n .filter(c => c.message !== undefined)\n .map(c => c.message ?? '');\n },\n },\n {\n severity: 6,\n errorExplanation: 'container-waiting',\n errorExists: pod => {\n return (pod.status?.containerStatuses ?? []).some(\n cs => cs.state?.waiting?.message !== undefined,\n );\n },\n messageAccessor: pod => {\n return (pod.status?.containerStatuses ?? [])\n .filter(cs => cs.state?.waiting?.message !== undefined)\n .map(cs => cs.state?.waiting?.message ?? '');\n },\n },\n {\n severity: 4,\n errorExplanation: 'container-last-state-error',\n errorExists: pod => {\n return (pod.status?.containerStatuses ?? []).some(\n cs => (cs.lastState?.terminated?.reason ?? '') === 'Error',\n );\n },\n messageAccessor: pod => {\n return (pod.status?.containerStatuses ?? [])\n .filter(cs => (cs.lastState?.terminated?.reason ?? '') === 'Error')\n .map(\n cs =>\n `container=${cs.name} exited with error code (${cs.lastState?.terminated?.exitCode})`,\n );\n },\n },\n];\n\nexport const detectErrorsInPods = (\n pods: V1Pod[],\n clusterName: string,\n): DetectedError[] =>\n detectErrorsInObjects(pods, 'Pod', clusterName, podErrorMappers);\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DetectedError, ErrorMapper } from './types';\nimport { V1Deployment } from '@kubernetes/client-node';\nimport { detectErrorsInObjects } from './common';\n\nconst deploymentErrorMappers: ErrorMapper<V1Deployment>[] = [\n {\n // this is probably important\n severity: 6,\n errorExplanation: 'condition-message-present',\n errorExists: deployment => {\n return (deployment.status?.conditions ?? [])\n .filter(c => c.status === 'False')\n .some(c => c.message !== undefined);\n },\n messageAccessor: deployment => {\n return (deployment.status?.conditions ?? [])\n .filter(c => c.status === 'False')\n .filter(c => c.message !== undefined)\n .map(c => c.message ?? '');\n },\n },\n];\n\nexport const detectErrorsInDeployments = (\n deployments: V1Deployment[],\n clusterName: string,\n): DetectedError[] =>\n detectErrorsInObjects(\n deployments,\n 'Deployment',\n clusterName,\n deploymentErrorMappers,\n );\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { V1HorizontalPodAutoscaler } from '@kubernetes/client-node';\nimport { DetectedError, ErrorMapper } from './types';\nimport { detectErrorsInObjects } from './common';\n\nconst hpaErrorMappers: ErrorMapper<V1HorizontalPodAutoscaler>[] = [\n {\n // this is probably important\n severity: 8,\n errorExplanation: 'hpa-max-current-replicas',\n errorExists: hpa => {\n return (hpa.spec?.maxReplicas ?? -1) === hpa.status?.currentReplicas;\n },\n messageAccessor: hpa => {\n return [\n `Current number of replicas (${\n hpa.status?.currentReplicas\n }) is equal to the configured max number of replicas (${\n hpa.spec?.maxReplicas ?? -1\n })`,\n ];\n },\n },\n];\n\nexport const detectErrorsInHpa = (\n hpas: V1HorizontalPodAutoscaler[],\n clusterName: string,\n): DetectedError[] =>\n detectErrorsInObjects(\n hpas,\n 'HorizontalPodAutoscaler',\n clusterName,\n hpaErrorMappers,\n );\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DetectedError, DetectedErrorsByCluster } from './types';\nimport { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common';\nimport { groupResponses } from '../utils/response';\nimport { detectErrorsInPods } from './pods';\nimport { detectErrorsInDeployments } from './deployments';\nimport { detectErrorsInHpa } from './hpas';\n\n// For each cluster try to find errors in each of the object types provided\n// returning a map of cluster names to errors in that cluster\nexport const detectErrors = (\n objects: ObjectsByEntityResponse,\n): DetectedErrorsByCluster => {\n const errors: DetectedErrorsByCluster = new Map<string, DetectedError[]>();\n\n for (const clusterResponse of objects.items) {\n let clusterErrors: DetectedError[] = [];\n\n const groupedResponses = groupResponses(clusterResponse.resources);\n\n clusterErrors = clusterErrors.concat(\n detectErrorsInPods(groupedResponses.pods, clusterResponse.cluster.name),\n );\n\n clusterErrors = clusterErrors.concat(\n detectErrorsInDeployments(\n groupedResponses.deployments,\n clusterResponse.cluster.name,\n ),\n );\n\n clusterErrors = clusterErrors.concat(\n detectErrorsInHpa(\n groupedResponses.horizontalPodAutoscalers,\n clusterResponse.cluster.name,\n ),\n );\n\n errors.set(clusterResponse.cluster.name, clusterErrors);\n }\n\n return errors;\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { ExtensionsV1beta1Ingress } from '@kubernetes/client-node';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\nimport { Typography, Grid } from '@material-ui/core';\n\nexport const IngressDrawer = ({\n ingress,\n expanded,\n}: {\n ingress: ExtensionsV1beta1Ingress;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={ingress}\n expanded={expanded}\n kind=\"Ingress\"\n renderObject={(ingressObject: ExtensionsV1beta1Ingress) => {\n return ingressObject.spec || {};\n }}\n >\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {ingress.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Ingress\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { ExtensionsV1beta1Ingress } from '@kubernetes/client-node';\nimport { IngressDrawer } from './IngressDrawer';\nimport { GroupedResponsesContext } from '../../hooks';\nimport { StructuredMetadataTable } from '@backstage/core-components';\n\ntype IngressesAccordionsProps = {};\n\ntype IngressAccordionProps = {\n ingress: ExtensionsV1beta1Ingress;\n};\n\ntype IngressSummaryProps = {\n ingress: ExtensionsV1beta1Ingress;\n};\n\nconst IngressSummary = ({ ingress }: IngressSummaryProps) => {\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"flex-start\"\n alignItems=\"center\"\n >\n <Grid xs={3} item>\n <IngressDrawer ingress={ingress} />\n </Grid>\n\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n </Grid>\n );\n};\n\ntype IngressCardProps = {\n ingress: ExtensionsV1beta1Ingress;\n};\n\nconst IngressCard = ({ ingress }: IngressCardProps) => {\n return (\n <StructuredMetadataTable\n metadata={{\n ...ingress.spec,\n }}\n />\n );\n};\n\nconst IngressAccordion = ({ ingress }: IngressAccordionProps) => {\n return (\n <Accordion TransitionProps={{ unmountOnExit: true }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <IngressSummary ingress={ingress} />\n </AccordionSummary>\n <AccordionDetails>\n <IngressCard ingress={ingress} />\n </AccordionDetails>\n </Accordion>\n );\n};\nexport const IngressesAccordions = ({}: IngressesAccordionsProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {groupedResponses.ingresses.map((ingress, i) => (\n <Grid item key={i} xs>\n <IngressAccordion ingress={ingress} />\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { V1Service } from '@kubernetes/client-node';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\nimport { Typography, Grid } from '@material-ui/core';\n\nexport const ServiceDrawer = ({\n service,\n expanded,\n}: {\n service: V1Service;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={service}\n expanded={expanded}\n kind=\"Service\"\n renderObject={(serviceObject: V1Service) => {\n return serviceObject.spec || {};\n }}\n >\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {service.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Service\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { V1Service } from '@kubernetes/client-node';\nimport { ServiceDrawer } from './ServiceDrawer';\nimport { GroupedResponsesContext } from '../../hooks';\nimport { StructuredMetadataTable } from '@backstage/core-components';\n\ntype ServiceSummaryProps = {\n service: V1Service;\n};\n\nconst ServiceSummary = ({ service }: ServiceSummaryProps) => {\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"flex-start\"\n alignItems=\"center\"\n >\n <Grid xs={3} item>\n <ServiceDrawer service={service} />\n </Grid>\n\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n\n <Grid item>\n <Typography variant=\"subtitle2\">\n Type: {service.spec?.type ?? '?'}\n </Typography>\n </Grid>\n </Grid>\n );\n};\n\ntype ServiceCardProps = {\n service: V1Service;\n};\n\nconst ServiceCard = ({ service }: ServiceCardProps) => {\n const metadata: any = {};\n\n if (service.status?.loadBalancer?.ingress?.length ?? -1 > 0) {\n metadata.loadbalancer = service.status?.loadBalancer;\n }\n\n if (service.spec?.type === 'ClusterIP') {\n metadata.clusterIP = service.spec.clusterIP;\n }\n if (service.spec?.type === 'ExternalName') {\n metadata.externalName = service.spec.externalName;\n }\n\n return (\n <StructuredMetadataTable\n metadata={{\n type: service.spec?.type,\n ports: service.spec?.ports,\n ...metadata,\n }}\n />\n );\n};\n\ntype ServicesAccordionsProps = {};\n\ntype ServiceAccordionProps = {\n service: V1Service;\n};\n\nconst ServiceAccordion = ({ service }: ServiceAccordionProps) => {\n return (\n <Accordion TransitionProps={{ unmountOnExit: true }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <ServiceSummary service={service} />\n </AccordionSummary>\n <AccordionDetails>\n <ServiceCard service={service} />\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport const ServicesAccordions = ({}: ServicesAccordionsProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {groupedResponses.services.map((service, i) => (\n <Grid item key={i} xs>\n <ServiceAccordion service={service} />\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { KubernetesDrawer } from '../../KubernetesDrawer/KubernetesDrawer';\nimport { Typography, Grid } from '@material-ui/core';\n\nexport const RolloutDrawer = ({\n rollout,\n expanded,\n}: {\n rollout: any;\n expanded?: boolean;\n}) => {\n return (\n <KubernetesDrawer\n object={rollout}\n expanded={expanded}\n kind=\"Rollout\"\n renderObject={() => ({})}\n >\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {rollout.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Rollout\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { Step, StepLabel, Stepper } from '@material-ui/core';\nimport {\n ArgoRolloutCanaryStep,\n SetWeightStep,\n PauseStep,\n AnalysisStep,\n} from './types';\n\ninterface StepsProgressProps {\n currentStepIndex: number;\n aborted: boolean;\n steps: ArgoRolloutCanaryStep[];\n children?: React.ReactNode;\n}\n\nconst isSetWeightStep = (step: ArgoRolloutCanaryStep): step is SetWeightStep =>\n step.hasOwnProperty('setWeight');\n\nconst isPauseStep = (step: ArgoRolloutCanaryStep): step is PauseStep =>\n step.hasOwnProperty('pause');\n\nconst isAnalysisStep = (step: ArgoRolloutCanaryStep): step is AnalysisStep =>\n step.hasOwnProperty('analysis');\n\nconst createLabelForStep = (step: ArgoRolloutCanaryStep): React.ReactNode => {\n if (isSetWeightStep(step)) {\n return `setWeight ${step.setWeight}%`;\n } else if (isPauseStep(step)) {\n return step.pause.duration === undefined\n ? 'infinite pause'\n : `pause for ${step.pause.duration}`;\n } else if (isAnalysisStep(step)) {\n return (\n <div>\n <p>analysis templates:</p>\n {step.analysis.templates.map((t, i) => (\n <p key={i}>{`${t.templateName}${\n t.clusterScope ? ' (cluster scoped)' : ''\n }`}</p>\n ))}\n </div>\n );\n }\n return 'unknown step';\n};\n\nexport const StepsProgress = ({\n currentStepIndex,\n aborted,\n steps,\n}: StepsProgressProps) => {\n // If the activeStep is greater/equal to the number of steps\n // Then the canary is being promoted\n // Increase the step index to mark the 'canary promoted' step as done also\n const activeStepIndex =\n currentStepIndex >= steps.length ? currentStepIndex + 1 : currentStepIndex;\n\n /*\n * When the Rollout is aborted set the active step to -1\n * otherwise it appears to always be on the first step\n */\n return (\n <Stepper activeStep={aborted ? -1 : activeStepIndex} alternativeLabel>\n {steps\n .map((step, i) => (\n <Step key={i}>\n <StepLabel data-testid={`step-${i}`}>\n {createLabelForStep(step)}\n </StepLabel>\n </Step>\n ))\n .concat(\n <Step key=\"-1\">\n <StepLabel data-testid=\"step--1\">Canary promoted</StepLabel>\n </Step>,\n )}\n </Stepper>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { V1Pod, V1HorizontalPodAutoscaler } from '@kubernetes/client-node';\nimport { PodsTable } from '../../Pods';\nimport { HorizontalPodAutoscalerDrawer } from '../../HorizontalPodAutoscalers';\nimport { RolloutDrawer } from './RolloutDrawer';\nimport PauseIcon from '@material-ui/icons/Pause';\nimport ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';\nimport { DateTime } from 'luxon';\nimport { StepsProgress } from './StepsProgress';\nimport {\n PodNamesWithErrorsContext,\n GroupedResponsesContext,\n} from '../../../hooks';\nimport {\n getMatchingHpa,\n getOwnedPodsThroughReplicaSets,\n} from '../../../utils/owner';\nimport { StatusError, StatusOK } from '@backstage/core-components';\n\ntype RolloutAccordionsProps = {\n rollouts: any[];\n defaultExpanded?: boolean;\n children?: React.ReactNode;\n};\n\ntype RolloutAccordionProps = {\n rollout: any;\n ownedPods: V1Pod[];\n defaultExpanded?: boolean;\n matchingHpa?: V1HorizontalPodAutoscaler;\n children?: React.ReactNode;\n};\n\ntype RolloutSummaryProps = {\n rollout: any;\n numberOfCurrentPods: number;\n numberOfPodsWithErrors: number;\n hpa?: V1HorizontalPodAutoscaler;\n children?: React.ReactNode;\n};\n\nconst AbortedTitle = (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n }}\n >\n <ErrorOutlineIcon />\n <Typography variant=\"subtitle1\">Aborted</Typography>\n </div>\n);\n\nconst findAbortedMessage = (rollout: any): string | undefined =>\n rollout.status?.conditions?.find(\n (c: any) =>\n c.type === 'Progressing' &&\n c.status === 'False' &&\n c.reason === 'RolloutAborted',\n )?.message;\n\nconst RolloutSummary = ({\n rollout,\n numberOfCurrentPods,\n numberOfPodsWithErrors,\n hpa,\n}: RolloutSummaryProps) => {\n const pauseTime: string | undefined = rollout.status?.pauseConditions?.find(\n (p: any) => p.reason === 'CanaryPauseStep',\n )?.startTime;\n const abortedMessage = findAbortedMessage(rollout);\n\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"flex-start\"\n alignItems=\"center\"\n >\n <Grid xs={3} item>\n <RolloutDrawer rollout={rollout} />\n </Grid>\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n {hpa && (\n <Grid item xs={3}>\n <HorizontalPodAutoscalerDrawer hpa={hpa}>\n <Grid\n item\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"subtitle2\">\n min replicas {hpa.spec?.minReplicas ?? '?'} / max replicas{' '}\n {hpa.spec?.maxReplicas ?? '?'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography variant=\"subtitle2\">\n current CPU usage:{' '}\n {hpa.status?.currentCPUUtilizationPercentage ?? '?'}%\n </Typography>\n </Grid>\n <Grid item>\n <Typography variant=\"subtitle2\">\n target CPU usage:{' '}\n {hpa.spec?.targetCPUUtilizationPercentage ?? '?'}%\n </Typography>\n </Grid>\n </Grid>\n </HorizontalPodAutoscalerDrawer>\n </Grid>\n )}\n <Grid\n item\n container\n xs={3}\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid item>\n <StatusOK>{numberOfCurrentPods} pods</StatusOK>\n </Grid>\n <Grid item>\n {numberOfPodsWithErrors > 0 ? (\n <StatusError>\n {numberOfPodsWithErrors} pod\n {numberOfPodsWithErrors > 1 ? 's' : ''} with errors\n </StatusError>\n ) : (\n <StatusOK>No pods with errors</StatusOK>\n )}\n </Grid>\n </Grid>\n {pauseTime && (\n <Grid item xs={3}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n }}\n >\n <PauseIcon />\n <Typography variant=\"subtitle1\">\n Paused ({DateTime.fromISO(pauseTime).toRelative({ locale: 'en' })}\n )\n </Typography>\n </div>\n </Grid>\n )}\n {abortedMessage && (\n <Grid item xs={3}>\n {AbortedTitle}\n </Grid>\n )}\n </Grid>\n );\n};\n\nconst RolloutAccordion = ({\n rollout,\n ownedPods,\n matchingHpa,\n defaultExpanded,\n}: RolloutAccordionProps) => {\n const podNamesWithErrors = useContext(PodNamesWithErrorsContext);\n\n const podsWithErrors = ownedPods.filter(p =>\n podNamesWithErrors.has(p.metadata?.name ?? ''),\n );\n\n const currentStepIndex = rollout.status?.currentStepIndex ?? 0;\n const abortedMessage = findAbortedMessage(rollout);\n\n return (\n <Accordion\n defaultExpanded={defaultExpanded}\n TransitionProps={{ unmountOnExit: true }}\n >\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <RolloutSummary\n rollout={rollout}\n numberOfCurrentPods={ownedPods.length}\n numberOfPodsWithErrors={podsWithErrors.length}\n hpa={matchingHpa}\n />\n </AccordionSummary>\n <AccordionDetails>\n <div style={{ width: '100%' }}>\n <div>\n <Typography variant=\"h6\">Rollout status</Typography>\n </div>\n <div style={{ margin: '1rem' }}>\n {abortedMessage && (\n <>\n {AbortedTitle}\n <Typography variant=\"subtitle2\">{abortedMessage}</Typography>\n </>\n )}\n <StepsProgress\n aborted={abortedMessage !== undefined}\n steps={rollout.spec?.strategy?.canary?.steps ?? []}\n currentStepIndex={currentStepIndex}\n />\n </div>\n <div>\n <PodsTable pods={ownedPods} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport const RolloutAccordions = ({\n rollouts,\n defaultExpanded = false,\n}: RolloutAccordionsProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n\n return (\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {rollouts.map((rollout, i) => (\n <Grid container item key={i} xs>\n <Grid item xs>\n <RolloutAccordion\n defaultExpanded={defaultExpanded}\n matchingHpa={getMatchingHpa(\n rollout.metadata?.name,\n 'rollout',\n groupedResponses.horizontalPodAutoscalers,\n )}\n ownedPods={getOwnedPodsThroughReplicaSets(\n rollout,\n groupedResponses.replicaSets,\n groupedResponses.pods,\n )}\n rollout={rollout}\n />\n </Grid>\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { KubernetesDrawer } from '../KubernetesDrawer/KubernetesDrawer';\nimport { Typography, Grid } from '@material-ui/core';\n\nconst capitalize = (str: string) =>\n str.charAt(0).toLocaleUpperCase('en-US') + str.slice(1);\n\nexport const DefaultCustomResourceDrawer = ({\n customResource,\n customResourceName,\n expanded,\n}: {\n customResource: any;\n customResourceName: string;\n expanded?: boolean;\n}) => {\n const capitalizedName = capitalize(customResourceName);\n\n return (\n <KubernetesDrawer\n object={customResource}\n expanded={expanded}\n kind={capitalizedName}\n renderObject={cr => cr}\n >\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item>\n <Typography variant=\"h5\">\n {customResource.metadata?.name ?? 'unknown object'}\n </Typography>\n </Grid>\n <Grid item>\n <Typography color=\"textSecondary\" variant=\"body1\">\n {capitalizedName}\n </Typography>\n </Grid>\n </Grid>\n </KubernetesDrawer>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { DefaultCustomResourceDrawer } from './DefaultCustomResourceDrawer';\nimport { StructuredMetadataTable } from '@backstage/core-components';\n\ntype DefaultCustomResourceAccordionsProps = {\n customResources: any[];\n customResourceName: string;\n defaultExpanded?: boolean;\n children?: React.ReactNode;\n};\n\ntype DefaultCustomResourceAccordionProps = {\n customResource: any;\n customResourceName: string;\n defaultExpanded?: boolean;\n children?: React.ReactNode;\n};\n\ntype DefaultCustomResourceSummaryProps = {\n customResource: any;\n customResourceName: string;\n children?: React.ReactNode;\n};\n\nconst DefaultCustomResourceSummary = ({\n customResource,\n customResourceName,\n}: DefaultCustomResourceSummaryProps) => {\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"flex-start\"\n alignItems=\"center\"\n >\n <Grid xs={3} item>\n <DefaultCustomResourceDrawer\n customResource={customResource}\n customResourceName={customResourceName}\n />\n </Grid>\n <Grid item xs={1}>\n <Divider style={{ height: '5em' }} orientation=\"vertical\" />\n </Grid>\n </Grid>\n );\n};\n\nconst DefaultCustomResourceAccordion = ({\n customResource,\n customResourceName,\n defaultExpanded,\n}: DefaultCustomResourceAccordionProps) => {\n return (\n <Accordion\n defaultExpanded={defaultExpanded}\n TransitionProps={{ unmountOnExit: true }}\n >\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <DefaultCustomResourceSummary\n customResource={customResource}\n customResourceName={customResourceName}\n />\n </AccordionSummary>\n <AccordionDetails>\n {customResource.hasOwnProperty('status') && (\n <StructuredMetadataTable metadata={customResource.status} />\n )}\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport const DefaultCustomResourceAccordions = ({\n customResources,\n customResourceName,\n defaultExpanded = false,\n}: DefaultCustomResourceAccordionsProps) => {\n return (\n <Grid\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n {customResources.map((cr, i) => (\n <Grid container item key={i} xs>\n <Grid item xs>\n <DefaultCustomResourceAccordion\n defaultExpanded={defaultExpanded}\n customResource={cr}\n customResourceName={customResourceName}\n />\n </Grid>\n </Grid>\n ))}\n </Grid>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useContext } from 'react';\nimport lodash, { Dictionary } from 'lodash';\nimport { RolloutAccordions } from './ArgoRollouts';\nimport { DefaultCustomResourceAccordions } from './DefaultCustomResource';\nimport { GroupedResponsesContext } from '../../hooks';\n\ninterface CustomResourcesProps {\n children?: React.ReactNode;\n}\n\nconst kindToResource = (customResources: any[]): Dictionary<any[]> => {\n return lodash.groupBy(customResources, value => {\n return value.kind;\n });\n};\n\nexport const CustomResources = ({}: CustomResourcesProps) => {\n const groupedResponses = useContext(GroupedResponsesContext);\n const kindToResourceMap = kindToResource(groupedResponses.customResources);\n\n return (\n <>\n {Object.entries(kindToResourceMap).map(([kind, resources], i) => {\n switch (kind) {\n case 'Rollout':\n return <RolloutAccordions key={i} rollouts={resources} />;\n default:\n return (\n <DefaultCustomResourceAccordions\n key={i}\n customResources={resources}\n customResourceName={kind}\n />\n );\n }\n })}\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n Accordion,\n AccordionDetails,\n AccordionSummary,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { Entity } from '@backstage/catalog-model';\nimport { ClusterObjects } from '@backstage/plugin-kubernetes-common';\nimport { ErrorPanel } from './ErrorPanel';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { DeploymentsAccordions } from '../DeploymentsAccordions';\nimport { ErrorReporting } from '../ErrorReporting';\nimport { groupResponses } from '../../utils/response';\nimport { DetectedError, detectErrors } from '../../error-detection';\nimport { IngressesAccordions } from '../IngressesAccordions';\nimport { ServicesAccordions } from '../ServicesAccordions';\nimport { CustomResources } from '../CustomResources';\nimport EmptyStateImage from '../../assets/emptystate.svg';\nimport {\n GroupedResponsesContext,\n PodNamesWithErrorsContext,\n useKubernetesObjects,\n} from '../../hooks';\n\nimport {\n Content,\n Page,\n Progress,\n StatusError,\n StatusOK,\n} from '@backstage/core-components';\n\ntype ClusterSummaryProps = {\n clusterName: string;\n totalNumberOfPods: number;\n numberOfPodsWithErrors: number;\n children?: React.ReactNode;\n};\n\nconst ClusterSummary = ({\n clusterName,\n totalNumberOfPods,\n numberOfPodsWithErrors,\n}: ClusterSummaryProps) => {\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid\n xs={4}\n item\n container\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n spacing={0}\n >\n <Grid item xs>\n <Typography variant=\"h3\">{clusterName}</Typography>\n <Typography color=\"textSecondary\" variant=\"body1\">\n Cluster\n </Typography>\n </Grid>\n </Grid>\n <Grid item xs={1}>\n <Divider style={{ height: '4em' }} orientation=\"vertical\" />\n </Grid>\n <Grid\n item\n container\n xs={3}\n direction=\"column\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n >\n <Grid item>\n <StatusOK>{totalNumberOfPods} pods</StatusOK>\n </Grid>\n <Grid item>\n {numberOfPodsWithErrors > 0 ? (\n <StatusError>{numberOfPodsWithErrors} pods with errors</StatusError>\n ) : (\n <StatusOK>No pods with errors</StatusOK>\n )}\n </Grid>\n </Grid>\n </Grid>\n );\n};\n\ntype ClusterProps = {\n clusterObjects: ClusterObjects;\n podsWithErrors: Set<string>;\n children?: React.ReactNode;\n};\n\nconst Cluster = ({ clusterObjects, podsWithErrors }: ClusterProps) => {\n const groupedResponses = groupResponses(clusterObjects.resources);\n return (\n <GroupedResponsesContext.Provider value={groupedResponses}>\n <PodNamesWithErrorsContext.Provider value={podsWithErrors}>\n <Accordion TransitionProps={{ unmountOnExit: true }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <ClusterSummary\n clusterName={clusterObjects.cluster.name}\n totalNumberOfPods={groupedResponses.pods.length}\n numberOfPodsWithErrors={podsWithErrors.size}\n />\n </AccordionSummary>\n <AccordionDetails>\n <Grid container direction=\"column\">\n <Grid item>\n <CustomResources />\n </Grid>\n <Grid item>\n <DeploymentsAccordions />\n </Grid>\n <Grid item>\n <IngressesAccordions />\n </Grid>\n <Grid item>\n <ServicesAccordions />\n </Grid>\n </Grid>\n </AccordionDetails>\n </Accordion>\n </PodNamesWithErrorsContext.Provider>\n </GroupedResponsesContext.Provider>\n );\n};\n\ntype KubernetesContentProps = { entity: Entity; children?: React.ReactNode };\n\nexport const KubernetesContent = ({ entity }: KubernetesContentProps) => {\n const { kubernetesObjects, error } = useKubernetesObjects(entity);\n\n const clustersWithErrors =\n kubernetesObjects?.items.filter(r => r.errors.length > 0) ?? [];\n\n const detectedErrors =\n kubernetesObjects !== undefined\n ? detectErrors(kubernetesObjects)\n : new Map<string, DetectedError[]>();\n\n return (\n <Page themeId=\"tool\">\n <Content>\n {kubernetesObjects === undefined && error === undefined && <Progress />}\n\n {/* errors retrieved from the kubernetes clusters */}\n {clustersWithErrors.length > 0 && (\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <ErrorPanel\n entityName={entity.metadata.name}\n clustersWithErrors={clustersWithErrors}\n />\n </Grid>\n </Grid>\n )}\n\n {/* other errors */}\n {error !== undefined && (\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <ErrorPanel\n entityName={entity.metadata.name}\n errorMessage={error}\n />\n </Grid>\n </Grid>\n )}\n\n {kubernetesObjects && (\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <ErrorReporting detectedErrors={detectedErrors} />\n </Grid>\n <Grid item>\n <Divider />\n </Grid>\n <Grid item>\n <Typography variant=\"h3\">Your Clusters</Typography>\n </Grid>\n <Grid item container>\n {kubernetesObjects?.items.length <= 0 && (\n <Grid\n container\n justifyContent=\"space-around\"\n direction=\"row\"\n alignItems=\"center\"\n spacing={2}\n >\n <Grid item xs={4}>\n <Typography variant=\"h5\">\n No resources on any known clusters for{' '}\n {entity.metadata.name}\n </Typography>\n </Grid>\n <Grid item xs={4}>\n <img\n src={EmptyStateImage}\n alt=\"EmptyState\"\n data-testid=\"emptyStateImg\"\n />\n </Grid>\n </Grid>\n )}\n {kubernetesObjects?.items.length > 0 &&\n kubernetesObjects?.items.map((item, i) => {\n const podsWithErrors = new Set<string>(\n detectedErrors\n .get(item.cluster.name)\n ?.filter(de => de.kind === 'Pod')\n .map(de => de.names)\n .flat() ?? [],\n );\n\n return (\n <Grid item key={i} xs={12}>\n <Cluster\n clusterObjects={item}\n podsWithErrors={podsWithErrors}\n />\n </Grid>\n );\n })}\n </Grid>\n </Grid>\n )}\n </Content>\n </Page>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { Entity } from '@backstage/catalog-model';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { Route, Routes } from 'react-router-dom';\nimport { rootCatalogKubernetesRouteRef } from './plugin';\nimport { KubernetesContent } from './components/KubernetesContent';\nimport { Button } from '@material-ui/core';\nimport { MissingAnnotationEmptyState } from '@backstage/core-components';\n\nconst KUBERNETES_ANNOTATION = 'backstage.io/kubernetes-id';\nconst KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION =\n 'backstage.io/kubernetes-label-selector';\n\ntype Props = {\n /** @deprecated The entity is now grabbed from context instead */\n entity?: Entity;\n};\n\nexport const Router = (_props: Props) => {\n const { entity } = useEntity();\n\n const kubernetesAnnotationValue =\n entity.metadata.annotations?.[KUBERNETES_ANNOTATION];\n\n const kubernetesLabelSelectorQueryAnnotationValue =\n entity.metadata.annotations?.[KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION];\n\n if (\n kubernetesAnnotationValue ||\n kubernetesLabelSelectorQueryAnnotationValue\n ) {\n return (\n <Routes>\n <Route\n path={`/${rootCatalogKubernetesRouteRef.path}`}\n element={<KubernetesContent entity={entity} />}\n />\n </Routes>\n );\n }\n\n return (\n <>\n <MissingAnnotationEmptyState annotation={KUBERNETES_ANNOTATION} />\n <h1>\n Or use a label selector query, which takes precedence over the previous\n annotation.\n </h1>\n <Button\n variant=\"contained\"\n color=\"primary\"\n href=\"https://backstage.io/docs/features/kubernetes/configuration#surfacing-your-kubernetes-components-as-part-of-an-entity\"\n >\n Read Kubernetes Plugin Docs\n </Button>\n </>\n );\n};\n"],"names":["columns","React"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/plugin-kubernetes",
3
- "version": "0.4.9",
3
+ "description": "A Backstage plugin that integrates towards Kubernetes",
4
+ "version": "0.4.13",
4
5
  "main": "dist/index.esm.js",
5
6
  "types": "dist/index.d.ts",
6
7
  "license": "Apache-2.0",
@@ -30,30 +31,30 @@
30
31
  "clean": "backstage-cli clean"
31
32
  },
32
33
  "dependencies": {
33
- "@backstage/catalog-model": "^0.9.0",
34
- "@backstage/config": "^0.1.5",
35
- "@backstage/core-components": "^0.2.0",
36
- "@backstage/core-plugin-api": "^0.1.4",
37
- "@backstage/plugin-catalog-react": "^0.4.0",
34
+ "@backstage/catalog-model": "^0.9.1",
35
+ "@backstage/config": "^0.1.6",
36
+ "@backstage/core-components": "^0.4.2",
37
+ "@backstage/core-plugin-api": "^0.1.8",
38
+ "@backstage/plugin-catalog-react": "^0.4.6",
38
39
  "@backstage/plugin-kubernetes-common": "^0.1.3",
39
- "@backstage/theme": "^0.2.9",
40
+ "@backstage/theme": "^0.2.10",
40
41
  "@kubernetes/client-node": "^0.15.0",
41
42
  "@material-ui/core": "^4.12.2",
42
43
  "@material-ui/icons": "^4.9.1",
43
- "@material-ui/lab": "4.0.0-alpha.45",
44
+ "@material-ui/lab": "4.0.0-alpha.57",
44
45
  "js-yaml": "^4.0.0",
45
46
  "lodash": "^4.17.21",
46
- "luxon": "^1.26.0",
47
+ "luxon": "^2.0.2",
47
48
  "react": "^16.13.1",
48
49
  "react-dom": "^16.13.1",
49
50
  "react-router-dom": "6.0.0-beta.0",
50
51
  "react-use": "^17.2.4"
51
52
  },
52
53
  "devDependencies": {
53
- "@backstage/cli": "^0.7.6",
54
- "@backstage/core-app-api": "^0.1.6",
55
- "@backstage/dev-utils": "^0.2.4",
56
- "@backstage/test-utils": "^0.1.16",
54
+ "@backstage/cli": "^0.7.12",
55
+ "@backstage/core-app-api": "^0.1.13",
56
+ "@backstage/dev-utils": "^0.2.9",
57
+ "@backstage/test-utils": "^0.1.17",
57
58
  "@testing-library/jest-dom": "^5.10.1",
58
59
  "@testing-library/react": "^11.2.5",
59
60
  "@testing-library/react-hooks": "^3.4.2",
@@ -66,5 +67,5 @@
66
67
  "files": [
67
68
  "dist"
68
69
  ],
69
- "gitHead": "c49b012d55e1a1716f05d3da84d22760ab2770e3"
70
+ "gitHead": "4dc47ebe3c30e9bdba9c2239aed9ece1a4d479a0"
70
71
  }