@backstage/plugin-kubernetes-backend 0.6.0 → 0.7.0-next.2

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,37 @@
1
1
  # @backstage/plugin-kubernetes-backend
2
2
 
3
+ ## 0.7.0-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 60e5f9fe68: Fixed the lack of `limitranges` as part of the Default Objects to fetch from the kubernetes api
8
+ - Updated dependencies
9
+ - @backstage/plugin-kubernetes-common@0.4.0-next.1
10
+ - @backstage/catalog-model@1.1.0-next.2
11
+ - @backstage/backend-common@0.14.1-next.2
12
+
13
+ ## 0.7.0-next.1
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+ - @backstage/catalog-model@1.1.0-next.1
19
+ - @backstage/backend-common@0.14.1-next.1
20
+ - @backstage/errors@1.1.0-next.0
21
+
22
+ ## 0.7.0-next.0
23
+
24
+ ### Minor Changes
25
+
26
+ - 0791af993f: Refactor `KubernetesObjectsProvider` with new methods, `KubernetesServiceLocator` now takes an `Entity` instead of `serviceId`
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies
31
+ - @backstage/backend-common@0.14.1-next.0
32
+ - @backstage/catalog-model@1.1.0-next.0
33
+ - @backstage/plugin-kubernetes-common@0.4.0-next.0
34
+
3
35
  ## 0.6.0
4
36
 
5
37
  ### Minor Changes
package/dist/index.cjs.js CHANGED
@@ -239,8 +239,8 @@ class MultiTenantServiceLocator {
239
239
  constructor(clusterSupplier) {
240
240
  this.clusterSupplier = clusterSupplier;
241
241
  }
242
- async getClustersByServiceId(_serviceId) {
243
- return this.clusterSupplier.getClusters();
242
+ getClustersByEntity(_entity) {
243
+ return this.clusterSupplier.getClusters().then((clusters) => ({ clusters }));
244
244
  }
245
245
  }
246
246
 
@@ -289,10 +289,9 @@ class KubernetesClientProvider {
289
289
  }
290
290
 
291
291
  class GoogleKubernetesAuthTranslator {
292
- async decorateClusterDetailsWithAuth(clusterDetails, requestBody) {
293
- var _a;
292
+ async decorateClusterDetailsWithAuth(clusterDetails, authConfig) {
294
293
  const clusterDetailsWithAuthToken = Object.assign({}, clusterDetails);
295
- const authToken = (_a = requestBody.auth) == null ? void 0 : _a.google;
294
+ const authToken = authConfig.google;
296
295
  if (authToken) {
297
296
  clusterDetailsWithAuthToken.serviceAccountToken = authToken;
298
297
  } else {
@@ -302,8 +301,8 @@ class GoogleKubernetesAuthTranslator {
302
301
  }
303
302
  }
304
303
 
305
- class ServiceAccountKubernetesAuthTranslator {
306
- async decorateClusterDetailsWithAuth(clusterDetails, _requestBody) {
304
+ class NoopKubernetesAuthTranslator {
305
+ async decorateClusterDetailsWithAuth(clusterDetails) {
307
306
  return clusterDetails;
308
307
  }
309
308
  }
@@ -448,14 +447,14 @@ class AzureIdentityKubernetesAuthTranslator {
448
447
  }
449
448
 
450
449
  class OidcKubernetesAuthTranslator {
451
- async decorateClusterDetailsWithAuth(clusterDetails, requestBody) {
452
- var _a, _b;
450
+ async decorateClusterDetailsWithAuth(clusterDetails, authConfig) {
451
+ var _a;
453
452
  const clusterDetailsWithAuthToken = Object.assign({}, clusterDetails);
454
453
  const { oidcTokenProvider } = clusterDetails;
455
454
  if (!oidcTokenProvider || oidcTokenProvider === "") {
456
455
  throw new Error(`oidc authProvider requires a configured oidcTokenProvider`);
457
456
  }
458
- const authToken = (_b = (_a = requestBody.auth) == null ? void 0 : _a.oidc) == null ? void 0 : _b[oidcTokenProvider];
457
+ const authToken = (_a = authConfig.oidc) == null ? void 0 : _a[oidcTokenProvider];
459
458
  if (authToken) {
460
459
  clusterDetailsWithAuthToken.serviceAccountToken = authToken;
461
460
  } else {
@@ -478,7 +477,7 @@ class KubernetesAuthTranslatorGenerator {
478
477
  return new AzureIdentityKubernetesAuthTranslator(options.logger);
479
478
  }
480
479
  case "serviceAccount": {
481
- return new ServiceAccountKubernetesAuthTranslator();
480
+ return new NoopKubernetesAuthTranslator();
482
481
  }
483
482
  case "googleServiceAccount": {
484
483
  return new GoogleServiceAccountAuthTranslator();
@@ -512,6 +511,12 @@ const DEFAULT_OBJECTS = [
512
511
  plural: "configmaps",
513
512
  objectType: "configmaps"
514
513
  },
514
+ {
515
+ group: "",
516
+ apiVersion: "v1",
517
+ plural: "limitranges",
518
+ objectType: "limitranges"
519
+ },
515
520
  {
516
521
  group: "apps",
517
522
  apiVersion: "v1",
@@ -599,28 +604,47 @@ class KubernetesFanOutHandler {
599
604
  this.objectTypesToFetch = new Set(objectTypesToFetch);
600
605
  this.authTranslators = {};
601
606
  }
602
- async getKubernetesObjectsByEntity(requestBody) {
603
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
604
- const entityName = ((_c = (_b = (_a = requestBody.entity) == null ? void 0 : _a.metadata) == null ? void 0 : _b.annotations) == null ? void 0 : _c["backstage.io/kubernetes-id"]) || ((_e = (_d = requestBody.entity) == null ? void 0 : _d.metadata) == null ? void 0 : _e.name);
605
- const clusterDetails = await this.serviceLocator.getClustersByServiceId(entityName);
606
- const promises = clusterDetails.map((cd) => {
607
- return this.getAuthTranslator(cd.authProvider).decorateClusterDetailsWithAuth(cd, requestBody);
608
- });
609
- const clusterDetailsDecoratedForAuth = await Promise.all(promises);
607
+ async getCustomResourcesByEntity({
608
+ entity,
609
+ auth,
610
+ customResources
611
+ }) {
612
+ return this.fanOutRequests(entity, auth, /* @__PURE__ */ new Set(), customResources);
613
+ }
614
+ async getKubernetesObjectsByEntity({
615
+ entity,
616
+ auth
617
+ }) {
618
+ return this.fanOutRequests(entity, auth, this.objectTypesToFetch, this.customResources);
619
+ }
620
+ async fanOutRequests(entity, auth, objectTypesToFetch, customResources) {
621
+ var _a, _b, _c, _d, _e, _f, _g;
622
+ const entityName = ((_b = (_a = entity.metadata) == null ? void 0 : _a.annotations) == null ? void 0 : _b["backstage.io/kubernetes-id"]) || ((_c = entity.metadata) == null ? void 0 : _c.name);
623
+ const clusterDetailsDecoratedForAuth = await this.decorateClusterDetailsWithAuth(entity, auth);
610
624
  this.logger.info(`entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth.map((c) => c.name).join(", ")}]`);
611
- const labelSelector = ((_h = (_g = (_f = requestBody.entity) == null ? void 0 : _f.metadata) == null ? void 0 : _g.annotations) == null ? void 0 : _h["backstage.io/kubernetes-label-selector"]) || `backstage.io/kubernetes-id=${entityName}`;
612
- const namespace = (_k = (_j = (_i = requestBody.entity) == null ? void 0 : _i.metadata) == null ? void 0 : _j.annotations) == null ? void 0 : _k["backstage.io/kubernetes-namespace"];
625
+ const labelSelector = ((_e = (_d = entity.metadata) == null ? void 0 : _d.annotations) == null ? void 0 : _e["backstage.io/kubernetes-label-selector"]) || `backstage.io/kubernetes-id=${entityName}`;
626
+ const namespace = (_g = (_f = entity.metadata) == null ? void 0 : _f.annotations) == null ? void 0 : _g["backstage.io/kubernetes-namespace"];
613
627
  return Promise.all(clusterDetailsDecoratedForAuth.map((clusterDetailsItem) => {
614
628
  return this.fetcher.fetchObjectsForService({
615
629
  serviceId: entityName,
616
630
  clusterDetails: clusterDetailsItem,
617
- objectTypesToFetch: this.objectTypesToFetch,
631
+ objectTypesToFetch,
618
632
  labelSelector,
619
- customResources: this.customResources,
633
+ customResources: customResources.map((c) => ({
634
+ ...c,
635
+ objectType: "customresources"
636
+ })),
620
637
  namespace
621
638
  }).then((result) => this.getMetricsForPods(clusterDetailsItem, result)).then((r) => this.toClusterObjects(clusterDetailsItem, r));
622
639
  })).then(this.toObjectsByEntityResponse);
623
640
  }
641
+ async decorateClusterDetailsWithAuth(entity, auth) {
642
+ const clusterDetails = await (await this.serviceLocator.getClustersByEntity(entity)).clusters;
643
+ return await Promise.all(clusterDetails.map((cd) => {
644
+ const kubernetesAuthTranslator = this.getAuthTranslator(cd.authProvider);
645
+ return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(cd, auth);
646
+ }));
647
+ }
624
648
  toObjectsByEntityResponse(clusterObjects) {
625
649
  return {
626
650
  items: clusterObjects.filter((item) => item.errors !== void 0 && item.errors.length >= 1 || item.resources !== void 0 && item.resources.length >= 1 && item.resources.some((fr) => fr.resources.length >= 1))
@@ -856,7 +880,10 @@ class KubernetesBuilder {
856
880
  const serviceId = req.params.serviceId;
857
881
  const requestBody = req.body;
858
882
  try {
859
- const response = await objectsProvider.getKubernetesObjectsByEntity(requestBody);
883
+ const response = await objectsProvider.getKubernetesObjectsByEntity({
884
+ entity: requestBody.entity,
885
+ auth: requestBody.auth || {}
886
+ });
860
887
  res.json(response);
861
888
  } catch (e) {
862
889
  logger.error(`action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/index.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesClientProvider.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/ServiceAccountKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"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 { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\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\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\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 { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\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 { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\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 ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async getClustersByServiceId(_serviceId: string): Promise<ClusterDetails[]> {\n return this.clusterSupplier.getClusters();\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 CoreV1Api,\n KubeConfig,\n Metrics,\n CustomObjectsApi,\n} from '@kubernetes/client-node';\nimport { ClusterDetails } from '../types/types';\n\nexport class KubernetesClientProvider {\n // visible for testing\n getKubeConfig(clusterDetails: ClusterDetails) {\n const cluster = {\n name: clusterDetails.name,\n server: clusterDetails.url,\n skipTLSVerify: clusterDetails.skipTLSVerify,\n caData: clusterDetails.caData,\n };\n\n // TODO configure\n const user = {\n name: 'backstage',\n token: clusterDetails.serviceAccountToken,\n };\n\n const context = {\n name: `${clusterDetails.name}`,\n user: user.name,\n cluster: cluster.name,\n };\n\n const kc = new KubeConfig();\n if (clusterDetails.serviceAccountToken) {\n kc.loadFromOptions({\n clusters: [cluster],\n users: [user],\n contexts: [context],\n currentContext: context.name,\n });\n } else {\n kc.loadFromDefault();\n }\n\n return kc;\n }\n\n getCoreClientByClusterDetails(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CoreV1Api);\n }\n\n getMetricsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return new Metrics(kc);\n }\n\n getCustomObjectsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CustomObjectsApi);\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 { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n requestBody: KubernetesRequestBody,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = requestBody.auth?.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\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 { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class ServiceAccountKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n _requestBody: KubernetesRequestBody,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\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 AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\ntype SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n return new Promise<SigningCreds>(async (resolve, reject) => {\n const awsCreds = await this.awsGetCredentials();\n\n if (!(awsCreds instanceof Credentials))\n return reject(Error('No AWS credentials found.'));\n\n let creds: SigningCreds = {\n accessKeyId: awsCreds.accessKeyId,\n secretAccessKey: awsCreds.secretAccessKey,\n sessionToken: awsCreds.sessionToken,\n };\n\n if (!this.validCredentials(creds))\n return reject(Error('Invalid AWS credentials found.'));\n if (!assumeRole) return resolve(creds);\n\n try {\n const params: AWS.STS.Types.AssumeRoleRequest = {\n RoleArn: assumeRole,\n RoleSessionName: 'backstage-login',\n };\n if (externalId) params.ExternalId = externalId;\n\n const assumedRole = await new AWS.STS().assumeRole(params).promise();\n\n if (!assumedRole.Credentials) {\n throw new Error(`No credentials returned for role ${assumeRole}`);\n }\n\n creds = {\n accessKeyId: assumedRole.Credentials.AccessKeyId,\n secretAccessKey: assumedRole.Credentials.SecretAccessKey,\n sessionToken: assumedRole.Credentials.SessionToken,\n };\n } catch (e) {\n console.warn(`There was an error assuming the role: ${e}`);\n return reject(Error(`Unable to assume role: ${e}`));\n }\n return resolve(creds);\n });\n }\n async getBearerToken(\n clusterName: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const credentials = await this.getCredentials(assumeRole, externalId);\n\n const request = {\n host: `sts.amazonaws.com`,\n path: `/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Expires=60`,\n headers: {\n 'x-k8s-aws-id': clusterName,\n },\n signQuery: true,\n };\n\n const signed = sign(request, credentials);\n const url = `https://${signed.host}${signed.path}`;\n const base64Url = Buffer.from(url, 'binary').toString('base64');\n const urlSafeBase64Url = base64Url\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return `k8s-aws-v1.${urlSafeBase64Url}`;\n }\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AWSClusterDetails,\n ): Promise<AWSClusterDetails> {\n const clusterDetailsWithAuthToken: AWSClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getBearerToken(\n clusterDetails.name,\n clusterDetails.assumeRole,\n clusterDetails.externalId,\n );\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 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 { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\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 { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\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 { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n requestBody: KubernetesRequestBody,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined =\n requestBody.auth?.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\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 { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { ServiceAccountKubernetesAuthTranslator } from './ServiceAccountKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n options: {\n logger: Logger;\n },\n ): KubernetesAuthTranslator {\n switch (authProvider) {\n case 'google': {\n return new GoogleKubernetesAuthTranslator();\n }\n case 'aws': {\n return new AwsIamKubernetesAuthTranslator();\n }\n case 'azure': {\n return new AzureIdentityKubernetesAuthTranslator(options.logger);\n }\n case 'serviceAccount': {\n return new ServiceAccountKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\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 { Logger } from 'winston';\nimport {\n ClusterDetails,\n CustomResource,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\nexport const DEFAULT_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'pods',\n objectType: 'pods',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'services',\n objectType: 'services',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'configmaps',\n objectType: 'configmaps',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: PodStatus[][],\n): ClientPodStatus[] => {\n return podMetrics.flat().map((pd: PodStatus): ClientPodStatus => {\n return {\n pod: pd.Pod,\n memory: toClientSafeResource(pd.Memory),\n cpu: toClientSafeResource(pd.CPU),\n containers: pd.Containers.map(toClientSafeContainer),\n };\n });\n};\n\ntype responseWithMetrics = [FetchResponseWrapper, PodStatus[][]];\n\nexport class KubernetesFanOutHandler {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslators: Record<string, KubernetesAuthTranslator>;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n }: KubernetesFanOutHandlerOptions) {\n this.logger = logger;\n this.fetcher = fetcher;\n this.serviceLocator = serviceLocator;\n this.customResources = customResources;\n this.objectTypesToFetch = new Set(objectTypesToFetch);\n this.authTranslators = {};\n }\n\n async getKubernetesObjectsByEntity(\n requestBody: KubernetesRequestBody,\n ): Promise<ObjectsByEntityResponse> {\n const entityName =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-id'\n ] || requestBody.entity?.metadata?.name;\n\n const clusterDetails: ClusterDetails[] =\n await this.serviceLocator.getClustersByServiceId(entityName);\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n const promises: Promise<ClusterDetails>[] = clusterDetails.map(cd => {\n return this.getAuthTranslator(\n cd.authProvider,\n ).decorateClusterDetailsWithAuth(cd, requestBody);\n });\n const clusterDetailsDecoratedForAuth: ClusterDetails[] = await Promise.all(\n promises,\n );\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-namespace'\n ];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: this.objectTypesToFetch,\n labelSelector,\n customResources: this.customResources,\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\n .then(r => this.toClusterObjects(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n const podMetrics = Array.from(namespaces).map(ns =>\n this.fetcher.fetchPodMetricsByNamespace(clusterDetails, ns),\n );\n\n return Promise.all([result, Promise.all(podMetrics)]);\n }\n\n private getAuthTranslator(provider: string): KubernetesAuthTranslator {\n if (this.authTranslators[provider]) {\n return this.authTranslators[provider];\n }\n\n this.authTranslators[provider] =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n provider,\n {\n logger: this.logger,\n },\n );\n return this.authTranslators[provider];\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 { CoreV1Api, topPods } from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n KubernetesObjectTypes,\n ObjectFetchParams,\n ObjectToFetch,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\n} from '@backstage/plugin-kubernetes-common';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport { PodStatus } from '@kubernetes/client-node/dist/top';\n\nexport interface Clients {\n core: CoreV1Api;\n}\n\nexport interface KubernetesClientBasedFetcherOptions {\n kubernetesClientProvider: KubernetesClientProvider;\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly kubernetesClientProvider: KubernetesClientProvider;\n private readonly logger: Logger;\n\n constructor({\n kubernetesClientProvider,\n logger,\n }: KubernetesClientBasedFetcherOptions) {\n this.kubernetesClientProvider = kubernetesClientProvider;\n this.logger = logger;\n }\n\n fetchObjectsForService(\n params: ObjectFetchParams,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(params.objectTypesToFetch)\n .concat(params.customResources)\n .map(toFetch => {\n return this.fetchResource(\n params.clusterDetails,\n toFetch,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n toFetch.objectType,\n params.namespace,\n ).catch(this.captureKubernetesErrorsRethrowOthers.bind(this));\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespace(\n clusterDetails: ClusterDetails,\n namespace: string,\n ): Promise<PodStatus[]> {\n const metricsClient =\n this.kubernetesClientProvider.getMetricsClient(clusterDetails);\n const coreApi =\n this.kubernetesClientProvider.getCoreClientByClusterDetails(\n clusterDetails,\n );\n\n return topPods(coreApi, metricsClient, namespace);\n }\n\n private captureKubernetesErrorsRethrowOthers(e: any): KubernetesFetchError {\n if (e.response && e.response.statusCode) {\n this.logger.warn(\n `statusCode=${e.response.statusCode} for resource ${\n e.response.request.uri.pathname\n } body=[${JSON.stringify(e.response.body)}]`,\n );\n return {\n errorType: statusCodeToErrorType(e.response.statusCode),\n statusCode: e.response.statusCode,\n resourcePath: e.response.request.uri.pathname,\n };\n }\n throw e;\n }\n\n private fetchResource(\n clusterDetails: ClusterDetails,\n resource: ObjectToFetch,\n labelSelector: string,\n objectType: KubernetesObjectTypes,\n namespace?: string,\n ): Promise<FetchResponse> {\n const customObjects =\n this.kubernetesClientProvider.getCustomObjectsClient(clusterDetails);\n\n customObjects.addInterceptor((requestOptions: any) => {\n requestOptions.uri = requestOptions.uri.replace('/apis//v1/', '/api/v1/');\n });\n\n if (namespace) {\n return customObjects\n .listNamespacedCustomObject(\n resource.group,\n resource.apiVersion,\n namespace,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n return customObjects\n .listClusterCustomObject(\n resource.group,\n resource.apiVersion,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\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 */\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport { Duration } from 'luxon';\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n KubernetesObjectTypes,\n ServiceLocatorMethod,\n CustomResource,\n KubernetesObjectsProvider,\n ObjectsByEntityRequest,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesServiceLocator,\n KubernetesObjectsProviderOptions,\n} from '../types/types';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\n\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @public\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.fetcher ?? this.buildFetcher();\n\n const clusterSupplier =\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval);\n\n const serviceLocator =\n this.serviceLocator ??\n this.buildServiceLocator(this.getServiceLocatorMethod(), clusterSupplier);\n\n const objectsProvider =\n this.objectsProvider ??\n this.buildObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(objectsProvider, clusterSupplier);\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n return getCombinedClusterSupplier(config, refreshInterval);\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n return new KubernetesFanOutHandler(options);\n }\n\n protected buildFetcher(): KubernetesFetcher {\n return new KubernetesClientBasedFetcher({\n kubernetesClientProvider: new KubernetesClientProvider(),\n logger: this.env.logger,\n });\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n return this.buildMultiTenantServiceLocator(clusterSupplier);\n case 'http':\n return this.buildHttpServiceLocator(clusterSupplier);\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use(express.json());\n\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity(\n requestBody,\n );\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\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 { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\n\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n clusterSupplier?: KubernetesClustersSupplier;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["container","ForwardedError","KubeConfig","CoreV1Api","Metrics","CustomObjectsApi","AWS","Credentials","sign","DefaultAzureCredential","lodash","topPods","Duration","Router","express"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/index.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesClientProvider.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"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 { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\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\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\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 { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\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 { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\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 { Entity } from '@backstage/catalog-model';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n getClustersByEntity(\n _entity: Entity,\n ): Promise<{ clusters: ClusterDetails[] }> {\n return this.clusterSupplier.getClusters().then(clusters => ({ clusters }));\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 CoreV1Api,\n KubeConfig,\n Metrics,\n CustomObjectsApi,\n} from '@kubernetes/client-node';\nimport { ClusterDetails } from '../types/types';\n\nexport class KubernetesClientProvider {\n // visible for testing\n getKubeConfig(clusterDetails: ClusterDetails) {\n const cluster = {\n name: clusterDetails.name,\n server: clusterDetails.url,\n skipTLSVerify: clusterDetails.skipTLSVerify,\n caData: clusterDetails.caData,\n };\n\n // TODO configure\n const user = {\n name: 'backstage',\n token: clusterDetails.serviceAccountToken,\n };\n\n const context = {\n name: `${clusterDetails.name}`,\n user: user.name,\n cluster: cluster.name,\n };\n\n const kc = new KubeConfig();\n if (clusterDetails.serviceAccountToken) {\n kc.loadFromOptions({\n clusters: [cluster],\n users: [user],\n contexts: [context],\n currentContext: context.name,\n });\n } else {\n kc.loadFromDefault();\n }\n\n return kc;\n }\n\n getCoreClientByClusterDetails(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CoreV1Api);\n }\n\n getMetricsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return new Metrics(kc);\n }\n\n getCustomObjectsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CustomObjectsApi);\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 { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = authConfig.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\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 { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\n\nexport class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\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 AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\ntype SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n return new Promise<SigningCreds>(async (resolve, reject) => {\n const awsCreds = await this.awsGetCredentials();\n\n if (!(awsCreds instanceof Credentials))\n return reject(Error('No AWS credentials found.'));\n\n let creds: SigningCreds = {\n accessKeyId: awsCreds.accessKeyId,\n secretAccessKey: awsCreds.secretAccessKey,\n sessionToken: awsCreds.sessionToken,\n };\n\n if (!this.validCredentials(creds))\n return reject(Error('Invalid AWS credentials found.'));\n if (!assumeRole) return resolve(creds);\n\n try {\n const params: AWS.STS.Types.AssumeRoleRequest = {\n RoleArn: assumeRole,\n RoleSessionName: 'backstage-login',\n };\n if (externalId) params.ExternalId = externalId;\n\n const assumedRole = await new AWS.STS().assumeRole(params).promise();\n\n if (!assumedRole.Credentials) {\n throw new Error(`No credentials returned for role ${assumeRole}`);\n }\n\n creds = {\n accessKeyId: assumedRole.Credentials.AccessKeyId,\n secretAccessKey: assumedRole.Credentials.SecretAccessKey,\n sessionToken: assumedRole.Credentials.SessionToken,\n };\n } catch (e) {\n console.warn(`There was an error assuming the role: ${e}`);\n return reject(Error(`Unable to assume role: ${e}`));\n }\n return resolve(creds);\n });\n }\n async getBearerToken(\n clusterName: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const credentials = await this.getCredentials(assumeRole, externalId);\n\n const request = {\n host: `sts.amazonaws.com`,\n path: `/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Expires=60`,\n headers: {\n 'x-k8s-aws-id': clusterName,\n },\n signQuery: true,\n };\n\n const signed = sign(request, credentials);\n const url = `https://${signed.host}${signed.path}`;\n const base64Url = Buffer.from(url, 'binary').toString('base64');\n const urlSafeBase64Url = base64Url\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return `k8s-aws-v1.${urlSafeBase64Url}`;\n }\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AWSClusterDetails,\n ): Promise<AWSClusterDetails> {\n const clusterDetailsWithAuthToken: AWSClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getBearerToken(\n clusterDetails.name,\n clusterDetails.assumeRole,\n clusterDetails.externalId,\n );\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 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 { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\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 { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\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 { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined = authConfig.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\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 { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { NoopKubernetesAuthTranslator } from './NoopKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n options: {\n logger: Logger;\n },\n ): KubernetesAuthTranslator {\n switch (authProvider) {\n case 'google': {\n return new GoogleKubernetesAuthTranslator();\n }\n case 'aws': {\n return new AwsIamKubernetesAuthTranslator();\n }\n case 'azure': {\n return new AzureIdentityKubernetesAuthTranslator(options.logger);\n }\n case 'serviceAccount': {\n return new NoopKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\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 { Logger } from 'winston';\nimport {\n ClusterDetails,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n CustomResource,\n CustomResourceMatcher,\n CustomResourcesByEntity,\n KubernetesObjectsByEntity,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n KubernetesRequestAuth,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\n/**\n *\n * @alpha\n */\nexport const DEFAULT_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'pods',\n objectType: 'pods',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'services',\n objectType: 'services',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'configmaps',\n objectType: 'configmaps',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'limitranges',\n objectType: 'limitranges',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: PodStatus[][],\n): ClientPodStatus[] => {\n return podMetrics.flat().map((pd: PodStatus): ClientPodStatus => {\n return {\n pod: pd.Pod,\n memory: toClientSafeResource(pd.Memory),\n cpu: toClientSafeResource(pd.CPU),\n containers: pd.Containers.map(toClientSafeContainer),\n };\n });\n};\n\ntype responseWithMetrics = [FetchResponseWrapper, PodStatus[][]];\n\nexport class KubernetesFanOutHandler {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslators: Record<string, KubernetesAuthTranslator>;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n }: KubernetesFanOutHandlerOptions) {\n this.logger = logger;\n this.fetcher = fetcher;\n this.serviceLocator = serviceLocator;\n this.customResources = customResources;\n this.objectTypesToFetch = new Set(objectTypesToFetch);\n this.authTranslators = {};\n }\n\n async getCustomResourcesByEntity({\n entity,\n auth,\n customResources,\n }: CustomResourcesByEntity): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity({\n entity,\n auth,\n }: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(\n entity,\n auth,\n this.objectTypesToFetch,\n this.customResources,\n );\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n objectTypesToFetch: Set<ObjectToFetch>,\n customResources: CustomResourceMatcher[],\n ) {\n const entityName =\n entity.metadata?.annotations?.['backstage.io/kubernetes-id'] ||\n entity.metadata?.name;\n\n const clusterDetailsDecoratedForAuth: ClusterDetails[] =\n await this.decorateClusterDetailsWithAuth(entity, auth);\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: objectTypesToFetch,\n labelSelector,\n customResources: customResources.map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\n .then(r => this.toClusterObjects(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n private async decorateClusterDetailsWithAuth(\n entity: Entity,\n auth: KubernetesRequestAuth,\n ) {\n const clusterDetails: ClusterDetails[] = await (\n await this.serviceLocator.getClustersByEntity(entity)\n ).clusters;\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n return await Promise.all(\n clusterDetails.map(cd => {\n const kubernetesAuthTranslator: KubernetesAuthTranslator =\n this.getAuthTranslator(cd.authProvider);\n return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(\n cd,\n auth,\n );\n }),\n );\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n const podMetrics = Array.from(namespaces).map(ns =>\n this.fetcher.fetchPodMetricsByNamespace(clusterDetails, ns),\n );\n\n return Promise.all([result, Promise.all(podMetrics)]);\n }\n\n private getAuthTranslator(provider: string): KubernetesAuthTranslator {\n if (this.authTranslators[provider]) {\n return this.authTranslators[provider];\n }\n\n this.authTranslators[provider] =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n provider,\n {\n logger: this.logger,\n },\n );\n return this.authTranslators[provider];\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 { CoreV1Api, topPods } from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n KubernetesObjectTypes,\n ObjectFetchParams,\n ObjectToFetch,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\n} from '@backstage/plugin-kubernetes-common';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport { PodStatus } from '@kubernetes/client-node/dist/top';\n\nexport interface Clients {\n core: CoreV1Api;\n}\n\nexport interface KubernetesClientBasedFetcherOptions {\n kubernetesClientProvider: KubernetesClientProvider;\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly kubernetesClientProvider: KubernetesClientProvider;\n private readonly logger: Logger;\n\n constructor({\n kubernetesClientProvider,\n logger,\n }: KubernetesClientBasedFetcherOptions) {\n this.kubernetesClientProvider = kubernetesClientProvider;\n this.logger = logger;\n }\n\n fetchObjectsForService(\n params: ObjectFetchParams,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(params.objectTypesToFetch)\n .concat(params.customResources)\n .map(toFetch => {\n return this.fetchResource(\n params.clusterDetails,\n toFetch,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n toFetch.objectType,\n params.namespace,\n ).catch(this.captureKubernetesErrorsRethrowOthers.bind(this));\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespace(\n clusterDetails: ClusterDetails,\n namespace: string,\n ): Promise<PodStatus[]> {\n const metricsClient =\n this.kubernetesClientProvider.getMetricsClient(clusterDetails);\n const coreApi =\n this.kubernetesClientProvider.getCoreClientByClusterDetails(\n clusterDetails,\n );\n\n return topPods(coreApi, metricsClient, namespace);\n }\n\n private captureKubernetesErrorsRethrowOthers(e: any): KubernetesFetchError {\n if (e.response && e.response.statusCode) {\n this.logger.warn(\n `statusCode=${e.response.statusCode} for resource ${\n e.response.request.uri.pathname\n } body=[${JSON.stringify(e.response.body)}]`,\n );\n return {\n errorType: statusCodeToErrorType(e.response.statusCode),\n statusCode: e.response.statusCode,\n resourcePath: e.response.request.uri.pathname,\n };\n }\n throw e;\n }\n\n private fetchResource(\n clusterDetails: ClusterDetails,\n resource: ObjectToFetch,\n labelSelector: string,\n objectType: KubernetesObjectTypes,\n namespace?: string,\n ): Promise<FetchResponse> {\n const customObjects =\n this.kubernetesClientProvider.getCustomObjectsClient(clusterDetails);\n\n customObjects.addInterceptor((requestOptions: any) => {\n requestOptions.uri = requestOptions.uri.replace('/apis//v1/', '/api/v1/');\n });\n\n if (namespace) {\n return customObjects\n .listNamespacedCustomObject(\n resource.group,\n resource.apiVersion,\n namespace,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n return customObjects\n .listClusterCustomObject(\n resource.group,\n resource.apiVersion,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\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 */\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport { Duration } from 'luxon';\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n KubernetesObjectTypes,\n ServiceLocatorMethod,\n CustomResource,\n KubernetesObjectsProvider,\n ObjectsByEntityRequest,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesServiceLocator,\n KubernetesObjectsProviderOptions,\n} from '../types/types';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\n\n/**\n *\n * @alpha\n */\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @alpha\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\n/**\n *\n * @alpha\n */\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.fetcher ?? this.buildFetcher();\n\n const clusterSupplier =\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval);\n\n const serviceLocator =\n this.serviceLocator ??\n this.buildServiceLocator(this.getServiceLocatorMethod(), clusterSupplier);\n\n const objectsProvider =\n this.objectsProvider ??\n this.buildObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(objectsProvider, clusterSupplier);\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n return getCombinedClusterSupplier(config, refreshInterval);\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n return new KubernetesFanOutHandler(options);\n }\n\n protected buildFetcher(): KubernetesFetcher {\n return new KubernetesClientBasedFetcher({\n kubernetesClientProvider: new KubernetesClientProvider(),\n logger: this.env.logger,\n });\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n return this.buildMultiTenantServiceLocator(clusterSupplier);\n case 'http':\n return this.buildHttpServiceLocator(clusterSupplier);\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use(express.json());\n\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity: requestBody.entity,\n auth: requestBody.auth || {},\n });\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\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 { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\n\n/**\n *\n * @alpha\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n clusterSupplier?: KubernetesClustersSupplier;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n *\n * @alpha\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["container","ForwardedError","KubeConfig","CoreV1Api","Metrics","CustomObjectsApi","AWS","Credentials","sign","DefaultAzureCredential","lodash","topPods","Duration","Router","express"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  import { Config } from '@backstage/config';
2
2
  import { Logger } from 'winston';
3
+ import { Entity } from '@backstage/catalog-model';
3
4
  import { JsonObject } from '@backstage/types';
4
- import { KubernetesFetchError, FetchResponse, KubernetesRequestBody, ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common';
5
+ import { KubernetesFetchError, FetchResponse, KubernetesRequestBody, KubernetesRequestAuth, ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common';
5
6
  import { PodStatus } from '@kubernetes/client-node/dist/top';
6
7
  import express from 'express';
7
8
  import { Duration } from 'luxon';
8
9
 
10
+ /**
11
+ *
12
+ * @alpha
13
+ */
9
14
  interface ObjectFetchParams {
10
15
  serviceId: string;
11
16
  clusterDetails: AWSClusterDetails | GKEClusterDetails | ServiceAccountClusterDetails | ClusterDetails;
@@ -14,24 +19,54 @@ interface ObjectFetchParams {
14
19
  customResources: CustomResource[];
15
20
  namespace?: string;
16
21
  }
22
+ /**
23
+ * Fetches information from a kubernetes cluster using the cluster details object to target a specific cluster
24
+ *
25
+ * @alpha
26
+ */
17
27
  interface KubernetesFetcher {
18
28
  fetchObjectsForService(params: ObjectFetchParams): Promise<FetchResponseWrapper>;
19
29
  fetchPodMetricsByNamespace(clusterDetails: ClusterDetails, namespace: string): Promise<PodStatus[]>;
20
30
  }
31
+ /**
32
+ *
33
+ * @alpha
34
+ */
21
35
  interface FetchResponseWrapper {
22
36
  errors: KubernetesFetchError[];
23
37
  responses: FetchResponse[];
24
38
  }
39
+ /**
40
+ *
41
+ * @alpha
42
+ */
25
43
  interface ObjectToFetch {
26
44
  objectType: KubernetesObjectTypes;
27
45
  group: string;
28
46
  apiVersion: string;
29
47
  plural: string;
30
48
  }
49
+ /**
50
+ *
51
+ * @alpha
52
+ */
31
53
  interface CustomResource extends ObjectToFetch {
32
54
  objectType: 'customresources';
33
55
  }
34
- declare type KubernetesObjectTypes = 'pods' | 'services' | 'configmaps' | 'deployments' | 'replicasets' | 'horizontalpodautoscalers' | 'jobs' | 'cronjobs' | 'ingresses' | 'customresources' | 'statefulsets';
56
+ /**
57
+ *
58
+ * @alpha
59
+ */
60
+ declare type CustomResourceMatcher = Omit<ObjectToFetch, 'objectType'>;
61
+ /**
62
+ *
63
+ * @alpha
64
+ */
65
+ declare type KubernetesObjectTypes = 'pods' | 'services' | 'configmaps' | 'deployments' | 'limitranges' | 'replicasets' | 'horizontalpodautoscalers' | 'jobs' | 'cronjobs' | 'ingresses' | 'customresources' | 'statefulsets';
66
+ /**
67
+ * Used to load cluster details from different sources
68
+ * @alpha
69
+ */
35
70
  interface KubernetesClustersSupplier {
36
71
  /**
37
72
  * Returns the cached list of clusters.
@@ -41,10 +76,24 @@ interface KubernetesClustersSupplier {
41
76
  */
42
77
  getClusters(): Promise<ClusterDetails[]>;
43
78
  }
79
+ /**
80
+ * Used to locate which cluster(s) a service is running on
81
+ * @alpha
82
+ */
44
83
  interface KubernetesServiceLocator {
45
- getClustersByServiceId(serviceId: string): Promise<ClusterDetails[]>;
84
+ getClustersByEntity(entity: Entity): Promise<{
85
+ clusters: ClusterDetails[];
86
+ }>;
46
87
  }
88
+ /**
89
+ *
90
+ * @alpha
91
+ */
47
92
  declare type ServiceLocatorMethod = 'multiTenant' | 'http';
93
+ /**
94
+ *
95
+ * @alpha
96
+ */
48
97
  interface ClusterDetails {
49
98
  /**
50
99
  * Specifies the name of the Kubernetes cluster.
@@ -97,16 +146,36 @@ interface ClusterDetails {
97
146
  */
98
147
  dashboardParameters?: JsonObject;
99
148
  }
149
+ /**
150
+ *
151
+ * @alpha
152
+ */
100
153
  interface GKEClusterDetails extends ClusterDetails {
101
154
  }
155
+ /**
156
+ *
157
+ * @alpha
158
+ */
102
159
  interface AzureClusterDetails extends ClusterDetails {
103
160
  }
161
+ /**
162
+ *
163
+ * @alpha
164
+ */
104
165
  interface ServiceAccountClusterDetails extends ClusterDetails {
105
166
  }
167
+ /**
168
+ *
169
+ * @alpha
170
+ */
106
171
  interface AWSClusterDetails extends ClusterDetails {
107
172
  assumeRole?: string;
108
173
  externalId?: string;
109
174
  }
175
+ /**
176
+ *
177
+ * @alpha
178
+ */
110
179
  interface KubernetesObjectsProviderOptions {
111
180
  logger: Logger;
112
181
  fetcher: KubernetesFetcher;
@@ -114,11 +183,39 @@ interface KubernetesObjectsProviderOptions {
114
183
  customResources: CustomResource[];
115
184
  objectTypesToFetch?: ObjectToFetch[];
116
185
  }
186
+ /**
187
+ *
188
+ * @alpha
189
+ */
117
190
  declare type ObjectsByEntityRequest = KubernetesRequestBody;
191
+ /**
192
+ *
193
+ * @alpha
194
+ */
195
+ interface KubernetesObjectsByEntity {
196
+ entity: Entity;
197
+ auth: KubernetesRequestAuth;
198
+ }
199
+ /**
200
+ *
201
+ * @alpha
202
+ */
203
+ interface CustomResourcesByEntity extends KubernetesObjectsByEntity {
204
+ customResources: CustomResourceMatcher[];
205
+ }
206
+ /**
207
+ *
208
+ * @alpha
209
+ */
118
210
  interface KubernetesObjectsProvider {
119
- getKubernetesObjectsByEntity(request: ObjectsByEntityRequest): Promise<ObjectsByEntityResponse>;
211
+ getKubernetesObjectsByEntity(kubernetesObjectsByEntity: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse>;
212
+ getCustomResourcesByEntity(customResourcesByEntity: CustomResourcesByEntity): Promise<ObjectsByEntityResponse>;
120
213
  }
121
214
 
215
+ /**
216
+ *
217
+ * @alpha
218
+ */
122
219
  interface RouterOptions {
123
220
  logger: Logger;
124
221
  config: Config;
@@ -136,9 +233,15 @@ interface RouterOptions {
136
233
  * config,
137
234
  * }).build();
138
235
  * ```
236
+ *
237
+ * @alpha
139
238
  */
140
239
  declare function createRouter(options: RouterOptions): Promise<express.Router>;
141
240
 
241
+ /**
242
+ *
243
+ * @alpha
244
+ */
142
245
  interface KubernetesEnvironment {
143
246
  logger: Logger;
144
247
  config: Config;
@@ -146,7 +249,7 @@ interface KubernetesEnvironment {
146
249
  /**
147
250
  * The return type of the `KubernetesBuilder.build` method
148
251
  *
149
- * @public
252
+ * @alpha
150
253
  */
151
254
  declare type KubernetesBuilderReturn = Promise<{
152
255
  router: express.Router;
@@ -156,6 +259,10 @@ declare type KubernetesBuilderReturn = Promise<{
156
259
  objectsProvider: KubernetesObjectsProvider;
157
260
  serviceLocator: KubernetesServiceLocator;
158
261
  }>;
262
+ /**
263
+ *
264
+ * @alpha
265
+ */
159
266
  declare class KubernetesBuilder {
160
267
  protected readonly env: KubernetesEnvironment;
161
268
  private clusterSupplier?;
@@ -184,6 +291,10 @@ declare class KubernetesBuilder {
184
291
  protected getObjectTypesToFetch(): ObjectToFetch[] | undefined;
185
292
  }
186
293
 
294
+ /**
295
+ *
296
+ * @alpha
297
+ */
187
298
  declare const DEFAULT_OBJECTS: ObjectToFetch[];
188
299
 
189
- export { AWSClusterDetails, AzureClusterDetails, ClusterDetails, CustomResource, DEFAULT_OBJECTS, FetchResponseWrapper, GKEClusterDetails, KubernetesBuilder, KubernetesBuilderReturn, KubernetesClustersSupplier, KubernetesEnvironment, KubernetesFetcher, KubernetesObjectTypes, KubernetesObjectsProvider, KubernetesObjectsProviderOptions, KubernetesServiceLocator, ObjectFetchParams, ObjectToFetch, ObjectsByEntityRequest, RouterOptions, ServiceAccountClusterDetails, ServiceLocatorMethod, createRouter };
300
+ export { AWSClusterDetails, AzureClusterDetails, ClusterDetails, CustomResource, CustomResourceMatcher, CustomResourcesByEntity, DEFAULT_OBJECTS, FetchResponseWrapper, GKEClusterDetails, KubernetesBuilder, KubernetesBuilderReturn, KubernetesClustersSupplier, KubernetesEnvironment, KubernetesFetcher, KubernetesObjectTypes, KubernetesObjectsByEntity, KubernetesObjectsProvider, KubernetesObjectsProviderOptions, KubernetesServiceLocator, ObjectFetchParams, ObjectToFetch, ObjectsByEntityRequest, RouterOptions, ServiceAccountClusterDetails, ServiceLocatorMethod, createRouter };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/plugin-kubernetes-backend",
3
3
  "description": "A Backstage backend plugin that integrates towards Kubernetes",
4
- "version": "0.6.0",
4
+ "version": "0.7.0-next.2",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -36,11 +36,11 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@azure/identity": "^2.0.4",
39
- "@backstage/backend-common": "^0.14.0",
40
- "@backstage/catalog-model": "^1.0.3",
39
+ "@backstage/backend-common": "^0.14.1-next.2",
40
+ "@backstage/catalog-model": "^1.1.0-next.2",
41
41
  "@backstage/config": "^1.0.1",
42
- "@backstage/errors": "^1.0.0",
43
- "@backstage/plugin-kubernetes-common": "^0.3.0",
42
+ "@backstage/errors": "^1.1.0-next.0",
43
+ "@backstage/plugin-kubernetes-common": "^0.4.0-next.1",
44
44
  "@google-cloud/container": "^4.0.0",
45
45
  "@kubernetes/client-node": "^0.16.0",
46
46
  "@types/express": "^4.17.6",
@@ -61,7 +61,7 @@
61
61
  "yn": "^4.0.0"
62
62
  },
63
63
  "devDependencies": {
64
- "@backstage/cli": "^0.17.2",
64
+ "@backstage/cli": "^0.18.0-next.2",
65
65
  "@types/aws4": "^1.5.1",
66
66
  "aws-sdk-mock": "^5.2.1",
67
67
  "supertest": "^6.1.3"
@@ -70,5 +70,5 @@
70
70
  "dist",
71
71
  "schema.d.ts"
72
72
  ],
73
- "gitHead": "e42cb3887e41f756c16380d757d93feda27f40ee"
73
+ "gitHead": "3eddfb061dd0abe711f4b88d2e0fb4b99e692978"
74
74
  }