@backstage/plugin-kubernetes-backend 0.20.0-next.1 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/config.d.ts +7 -0
  3. package/dist/auth/AksStrategy.cjs.js.map +1 -1
  4. package/dist/auth/AnonymousStrategy.cjs.js.map +1 -1
  5. package/dist/auth/AwsIamStrategy.cjs.js.map +1 -1
  6. package/dist/auth/AzureIdentityStrategy.cjs.js.map +1 -1
  7. package/dist/auth/DispatchStrategy.cjs.js.map +1 -1
  8. package/dist/auth/GoogleServiceAccountStrategy.cjs.js +22 -2
  9. package/dist/auth/GoogleServiceAccountStrategy.cjs.js.map +1 -1
  10. package/dist/auth/GoogleStrategy.cjs.js.map +1 -1
  11. package/dist/auth/OidcStrategy.cjs.js.map +1 -1
  12. package/dist/auth/ServiceAccountStrategy.cjs.js.map +1 -1
  13. package/dist/auth/buildDefaultAuthStrategyMap.cjs.js +27 -0
  14. package/dist/auth/buildDefaultAuthStrategyMap.cjs.js.map +1 -0
  15. package/dist/auth/requirePermission.cjs.js.map +1 -1
  16. package/dist/cluster-locator/CatalogClusterLocator.cjs.js +7 -10
  17. package/dist/cluster-locator/CatalogClusterLocator.cjs.js.map +1 -1
  18. package/dist/cluster-locator/ConfigClusterLocator.cjs.js.map +1 -1
  19. package/dist/cluster-locator/GkeClusterLocator.cjs.js.map +1 -1
  20. package/dist/cluster-locator/LocalKubectlProxyLocator.cjs.js.map +1 -1
  21. package/dist/cluster-locator/index.cjs.js +2 -2
  22. package/dist/cluster-locator/index.cjs.js.map +1 -1
  23. package/dist/index.d.ts +26 -1
  24. package/dist/package.json.cjs.js +2 -127
  25. package/dist/package.json.cjs.js.map +1 -1
  26. package/dist/plugin.cjs.js +60 -25
  27. package/dist/plugin.cjs.js.map +1 -1
  28. package/dist/routes/resourcesRoutes.cjs.js +3 -5
  29. package/dist/routes/resourcesRoutes.cjs.js.map +1 -1
  30. package/dist/service/KubernetesFanOutHandler.cjs.js.map +1 -1
  31. package/dist/service/KubernetesFetcher.cjs.js.map +1 -1
  32. package/dist/service/KubernetesInitializer.cjs.js +143 -0
  33. package/dist/service/KubernetesInitializer.cjs.js.map +1 -0
  34. package/dist/service/KubernetesProxy.cjs.js.map +1 -1
  35. package/dist/service/KubernetesRouter.cjs.js +167 -0
  36. package/dist/service/KubernetesRouter.cjs.js.map +1 -0
  37. package/dist/service/runPeriodically.cjs.js.map +1 -1
  38. package/dist/service-locator/CatalogRelationServiceLocator.cjs.js.map +1 -1
  39. package/dist/service-locator/MultiTenantServiceLocator.cjs.js.map +1 -1
  40. package/dist/service-locator/SingleTenantServiceLocator.cjs.js.map +1 -1
  41. package/dist/service-locator/buildDefaultServiceLocator.cjs.js +31 -0
  42. package/dist/service-locator/buildDefaultServiceLocator.cjs.js.map +1 -0
  43. package/package.json +20 -20
  44. package/dist/service/KubernetesBuilder.cjs.js +0 -374
  45. package/dist/service/KubernetesBuilder.cjs.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
2
- import { LoggerService, PermissionsService, DiscoveryService, HttpAuthService } from '@backstage/backend-plugin-api';
2
+ import { LoggerService, DiscoveryService, HttpAuthService, PermissionsService } from '@backstage/backend-plugin-api';
3
3
  import * as k8sTypes from '@backstage/plugin-kubernetes-node';
4
4
  import { AuthenticationStrategy, ClusterDetails, KubernetesCredential, AuthMetadata, ObjectToFetch, KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node';
5
5
  import { KubernetesRequestAuth, KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
@@ -86,10 +86,35 @@ declare class GoogleStrategy implements AuthenticationStrategy {
86
86
  }
87
87
 
88
88
  /**
89
+ * GoogleServiceAccountStrategy provides authentication using Google Service Account credentials.
90
+ *
91
+ * Credentials can be provided via configuration:
92
+ * ```yaml
93
+ * kubernetes:
94
+ * googleServiceAccountCredentials: |
95
+ * {
96
+ * "type": "service_account",
97
+ * "project_id": "your-project-id",
98
+ * "private_key_id": "key-id",
99
+ * "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
100
+ * "client_email": "your-service-account@your-project.iam.gserviceaccount.com",
101
+ * "client_id": "client-id",
102
+ * "auth_uri": "https://accounts.google.com/o/oauth2/auth",
103
+ * "token_uri": "https://oauth2.googleapis.com/token",
104
+ * "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
105
+ * "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/..."
106
+ * }
107
+ * ```
108
+ *
109
+ * If no credentials are provided in config, falls back to GOOGLE_APPLICATION_CREDENTIALS or ADC.
89
110
  *
90
111
  * @public
91
112
  */
92
113
  declare class GoogleServiceAccountStrategy implements AuthenticationStrategy {
114
+ private readonly credentials?;
115
+ constructor(opts: {
116
+ config: Config;
117
+ });
93
118
  getCredential(): Promise<KubernetesCredential>;
94
119
  validateCluster(): Error[];
95
120
  presentAuthMetadata(_authMetadata: AuthMetadata): AuthMetadata;
@@ -2,135 +2,10 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var name = "@backstage/plugin-kubernetes-backend";
6
- var version = "0.20.0-next.1";
7
- var description = "A Backstage backend plugin that integrates towards Kubernetes";
8
- var backstage = {
9
- role: "backend-plugin",
10
- pluginId: "kubernetes",
11
- pluginPackages: [
12
- "@backstage/plugin-kubernetes",
13
- "@backstage/plugin-kubernetes-backend",
14
- "@backstage/plugin-kubernetes-common",
15
- "@backstage/plugin-kubernetes-node",
16
- "@backstage/plugin-kubernetes-react"
17
- ]
18
- };
19
- var publishConfig = {
20
- access: "public"
21
- };
22
- var keywords = [
23
- "backstage",
24
- "kubernetes"
25
- ];
26
- var homepage = "https://backstage.io";
27
- var repository = {
28
- type: "git",
29
- url: "https://github.com/backstage/backstage",
30
- directory: "plugins/kubernetes-backend"
31
- };
32
- var license = "Apache-2.0";
33
- var main = "src/index.ts";
34
- var types = "src/index.ts";
35
- var files = [
36
- "dist",
37
- "config.d.ts"
38
- ];
39
- var scripts = {
40
- build: "backstage-cli package build",
41
- clean: "backstage-cli package clean",
42
- lint: "backstage-cli package lint",
43
- prepack: "backstage-cli package prepack",
44
- postpack: "backstage-cli package postpack",
45
- start: "backstage-cli package start",
46
- test: "backstage-cli package test"
47
- };
48
- var dependencies = {
49
- "@aws-crypto/sha256-js": "^5.0.0",
50
- "@aws-sdk/credential-providers": "^3.350.0",
51
- "@aws-sdk/signature-v4": "^3.347.0",
52
- "@azure/identity": "^4.0.0",
53
- "@backstage/backend-plugin-api": "workspace:^",
54
- "@backstage/catalog-client": "workspace:^",
55
- "@backstage/catalog-model": "workspace:^",
56
- "@backstage/config": "workspace:^",
57
- "@backstage/errors": "workspace:^",
58
- "@backstage/integration-aws-node": "workspace:^",
59
- "@backstage/plugin-auth-node": "workspace:^",
60
- "@backstage/plugin-catalog-node": "workspace:^",
61
- "@backstage/plugin-kubernetes-common": "workspace:^",
62
- "@backstage/plugin-kubernetes-node": "workspace:^",
63
- "@backstage/plugin-permission-common": "workspace:^",
64
- "@backstage/plugin-permission-node": "workspace:^",
65
- "@backstage/types": "workspace:^",
66
- "@google-cloud/container": "^5.0.0",
67
- "@jest-mock/express": "^2.0.1",
68
- "@kubernetes/client-node": "1.1.2",
69
- "@types/http-proxy-middleware": "^1.0.0",
70
- compression: "^1.7.4",
71
- cors: "^2.8.5",
72
- express: "^4.17.1",
73
- "express-promise-router": "^4.1.0",
74
- "fs-extra": "^11.2.0",
75
- helmet: "^6.0.0",
76
- "http-proxy-middleware": "^2.0.6",
77
- lodash: "^4.17.21",
78
- luxon: "^3.0.0",
79
- morgan: "^1.10.0",
80
- "node-fetch": "^2.7.0",
81
- "stream-buffers": "^3.0.2",
82
- winston: "^3.2.1",
83
- yn: "^4.0.0"
84
- };
85
- var devDependencies = {
86
- "@backstage/backend-app-api": "workspace:^",
87
- "@backstage/backend-defaults": "workspace:^",
88
- "@backstage/backend-test-utils": "workspace:^",
89
- "@backstage/cli": "workspace:^",
90
- "@backstage/plugin-permission-backend": "workspace:^",
91
- "@backstage/plugin-permission-backend-module-allow-all-policy": "workspace:^",
92
- "@types/aws4": "^1.5.1",
93
- "@types/express": "^4.17.6",
94
- "@types/luxon": "^3.0.0",
95
- msw: "^1.0.0",
96
- supertest: "^7.0.0",
97
- ws: "^8.18.0"
98
- };
99
- var configSchema = "config.d.ts";
5
+ var version = "0.20.0";
100
6
  var packageinfo = {
101
- name: name,
102
- version: version,
103
- description: description,
104
- backstage: backstage,
105
- publishConfig: publishConfig,
106
- keywords: keywords,
107
- homepage: homepage,
108
- repository: repository,
109
- license: license,
110
- main: main,
111
- types: types,
112
- files: files,
113
- scripts: scripts,
114
- dependencies: dependencies,
115
- devDependencies: devDependencies,
116
- configSchema: configSchema
117
- };
7
+ version: version};
118
8
 
119
- exports.backstage = backstage;
120
- exports.configSchema = configSchema;
121
9
  exports.default = packageinfo;
122
- exports.dependencies = dependencies;
123
- exports.description = description;
124
- exports.devDependencies = devDependencies;
125
- exports.files = files;
126
- exports.homepage = homepage;
127
- exports.keywords = keywords;
128
- exports.license = license;
129
- exports.main = main;
130
- exports.name = name;
131
- exports.publishConfig = publishConfig;
132
- exports.repository = repository;
133
- exports.scripts = scripts;
134
- exports.types = types;
135
10
  exports.version = version;
136
11
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"package.json.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"package.json.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
- var alpha = require('@backstage/plugin-catalog-node/alpha');
4
+ var pluginCatalogNode = require('@backstage/plugin-catalog-node');
5
5
  var pluginKubernetesNode = require('@backstage/plugin-kubernetes-node');
6
- var KubernetesBuilder = require('./service/KubernetesBuilder.cjs.js');
6
+ var KubernetesRouter = require('./service/KubernetesRouter.cjs.js');
7
+ var KubernetesInitializer = require('./service/KubernetesInitializer.cjs.js');
7
8
 
8
9
  class ObjectsProvider {
9
10
  objectsProvider;
@@ -16,7 +17,11 @@ class ObjectsProvider {
16
17
  "Multiple Kubernetes objects provider is not supported at this time"
17
18
  );
18
19
  }
19
- this.objectsProvider = provider;
20
+ if (typeof provider !== "function") {
21
+ this.objectsProvider = async () => provider;
22
+ } else {
23
+ this.objectsProvider = provider;
24
+ }
20
25
  }
21
26
  }
22
27
  class ClusterSuplier {
@@ -30,7 +35,11 @@ class ClusterSuplier {
30
35
  "Multiple Kubernetes Cluster Suppliers is not supported at this time"
31
36
  );
32
37
  }
33
- this.clusterSupplier = clusterSupplier;
38
+ if (typeof clusterSupplier !== "function") {
39
+ this.clusterSupplier = async () => clusterSupplier;
40
+ } else {
41
+ this.clusterSupplier = clusterSupplier;
42
+ }
34
43
  }
35
44
  }
36
45
  class Fetcher {
@@ -44,7 +53,11 @@ class Fetcher {
44
53
  "Multiple Kubernetes Fetchers is not supported at this time"
45
54
  );
46
55
  }
47
- this.fetcher = fetcher;
56
+ if (typeof fetcher !== "function") {
57
+ this.fetcher = async () => fetcher;
58
+ } else {
59
+ this.fetcher = fetcher;
60
+ }
48
61
  }
49
62
  }
50
63
  class ServiceLocator {
@@ -58,22 +71,26 @@ class ServiceLocator {
58
71
  "Multiple Kubernetes Service Locators is not supported at this time"
59
72
  );
60
73
  }
61
- this.serviceLocator = serviceLocator;
74
+ if (typeof serviceLocator !== "function") {
75
+ this.serviceLocator = async () => serviceLocator;
76
+ } else {
77
+ this.serviceLocator = serviceLocator;
78
+ }
62
79
  }
63
80
  }
64
81
  class AuthStrategy {
65
82
  authStrategies;
66
- constructor() {
67
- this.authStrategies = new Array();
68
- }
69
- static addAuthStrategiesFromArray(authStrategies, builder) {
70
- authStrategies.forEach((st) => builder.addAuthStrategy(st.key, st.strategy));
71
- }
72
83
  getAuthenticationStrategies() {
73
84
  return this.authStrategies;
74
85
  }
75
86
  addAuthStrategy(key, authStrategy) {
76
- this.authStrategies.push({ key, strategy: authStrategy });
87
+ if (!this.authStrategies) {
88
+ this.authStrategies = /* @__PURE__ */ new Map();
89
+ }
90
+ if (key.includes("-")) {
91
+ throw new Error("Strategy name can not include dashes");
92
+ }
93
+ this.authStrategies.set(key, authStrategy);
77
94
  }
78
95
  }
79
96
  const kubernetesPlugin = backendPluginApi.createBackendPlugin({
@@ -110,7 +127,7 @@ const kubernetesPlugin = backendPluginApi.createBackendPlugin({
110
127
  logger: backendPluginApi.coreServices.logger,
111
128
  config: backendPluginApi.coreServices.rootConfig,
112
129
  discovery: backendPluginApi.coreServices.discovery,
113
- catalogApi: alpha.catalogServiceRef,
130
+ catalog: pluginCatalogNode.catalogServiceRef,
114
131
  permissions: backendPluginApi.coreServices.permissions,
115
132
  auth: backendPluginApi.coreServices.auth,
116
133
  httpAuth: backendPluginApi.coreServices.httpAuth
@@ -120,27 +137,45 @@ const kubernetesPlugin = backendPluginApi.createBackendPlugin({
120
137
  logger,
121
138
  config,
122
139
  discovery,
123
- catalogApi,
140
+ catalog,
124
141
  permissions,
125
142
  auth,
126
143
  httpAuth
127
144
  }) {
128
145
  if (config.has("kubernetes")) {
129
- const builder = KubernetesBuilder.KubernetesBuilder.createBuilder({
146
+ const initializer = KubernetesInitializer.KubernetesInitializer.create({
147
+ logger,
148
+ config,
149
+ catalog,
150
+ auth,
151
+ fetcher: extPointFetcher.getFetcher(),
152
+ clusterSupplier: extPointClusterSuplier.getClusterSupplier(),
153
+ serviceLocator: extPointServiceLocator.getServiceLocator(),
154
+ objectsProvider: extPointObjectsProvider.getObjectsProvider(),
155
+ authStrategyMap: extPointAuthStrategy.getAuthenticationStrategies()
156
+ });
157
+ const {
158
+ fetcher,
159
+ authStrategyMap,
160
+ clusterSupplier,
161
+ serviceLocator,
162
+ objectsProvider
163
+ } = await initializer.init();
164
+ const router = KubernetesRouter.KubernetesRouter.create({
130
165
  logger,
131
166
  config,
132
- catalogApi,
167
+ catalog,
133
168
  permissions,
134
169
  discovery,
135
170
  auth,
136
- httpAuth
137
- }).setObjectsProvider(extPointObjectsProvider.getObjectsProvider()).setClusterSupplier(extPointClusterSuplier.getClusterSupplier()).setFetcher(extPointFetcher.getFetcher()).setServiceLocator(extPointServiceLocator.getServiceLocator());
138
- AuthStrategy.addAuthStrategiesFromArray(
139
- extPointAuthStrategy.getAuthenticationStrategies(),
140
- builder
141
- );
142
- const { router } = await builder.build();
143
- http.use(router);
171
+ httpAuth,
172
+ authStrategyMap: Object.fromEntries(authStrategyMap.entries()),
173
+ fetcher,
174
+ clusterSupplier,
175
+ serviceLocator,
176
+ objectsProvider
177
+ });
178
+ http.use(await router.getRouter());
144
179
  } else {
145
180
  logger.warn(
146
181
  "Failed to initialize kubernetes backend: valid kubernetes config is missing"
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 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 coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\n\nimport {\n type AuthenticationStrategy,\n kubernetesAuthStrategyExtensionPoint,\n type KubernetesAuthStrategyExtensionPoint,\n type KubernetesClustersSupplier,\n kubernetesClusterSupplierExtensionPoint,\n type KubernetesClusterSupplierExtensionPoint,\n type KubernetesFetcher,\n kubernetesFetcherExtensionPoint,\n type KubernetesFetcherExtensionPoint,\n type KubernetesObjectsProvider,\n kubernetesObjectsProviderExtensionPoint,\n type KubernetesObjectsProviderExtensionPoint,\n type KubernetesServiceLocator,\n kubernetesServiceLocatorExtensionPoint,\n type KubernetesServiceLocatorExtensionPoint,\n} from '@backstage/plugin-kubernetes-node';\nimport { KubernetesBuilder } from './service/KubernetesBuilder';\n\nclass ObjectsProvider implements KubernetesObjectsProviderExtensionPoint {\n private objectsProvider: KubernetesObjectsProvider | undefined;\n\n getObjectsProvider() {\n return this.objectsProvider;\n }\n\n addObjectsProvider(provider: KubernetesObjectsProvider) {\n if (this.objectsProvider) {\n throw new Error(\n 'Multiple Kubernetes objects provider is not supported at this time',\n );\n }\n this.objectsProvider = provider;\n }\n}\n\nclass ClusterSuplier implements KubernetesClusterSupplierExtensionPoint {\n private clusterSupplier: KubernetesClustersSupplier | undefined;\n\n getClusterSupplier() {\n return this.clusterSupplier;\n }\n\n addClusterSupplier(clusterSupplier: KubernetesClustersSupplier) {\n if (this.clusterSupplier) {\n throw new Error(\n 'Multiple Kubernetes Cluster Suppliers is not supported at this time',\n );\n }\n this.clusterSupplier = clusterSupplier;\n }\n}\n\nclass Fetcher implements KubernetesFetcherExtensionPoint {\n private fetcher: KubernetesFetcher | undefined;\n\n getFetcher() {\n return this.fetcher;\n }\n\n addFetcher(fetcher: KubernetesFetcher) {\n if (this.fetcher) {\n throw new Error(\n 'Multiple Kubernetes Fetchers is not supported at this time',\n );\n }\n this.fetcher = fetcher;\n }\n}\n\nclass ServiceLocator implements KubernetesServiceLocatorExtensionPoint {\n private serviceLocator: KubernetesServiceLocator | undefined;\n\n getServiceLocator() {\n return this.serviceLocator;\n }\n\n addServiceLocator(serviceLocator: KubernetesServiceLocator) {\n if (this.serviceLocator) {\n throw new Error(\n 'Multiple Kubernetes Service Locators is not supported at this time',\n );\n }\n this.serviceLocator = serviceLocator;\n }\n}\n\nclass AuthStrategy implements KubernetesAuthStrategyExtensionPoint {\n private authStrategies: Array<{\n key: string;\n strategy: AuthenticationStrategy;\n }>;\n\n constructor() {\n this.authStrategies = new Array<{\n key: string;\n strategy: AuthenticationStrategy;\n }>();\n }\n\n static addAuthStrategiesFromArray(\n authStrategies: Array<{ key: string; strategy: AuthenticationStrategy }>,\n builder: KubernetesBuilder,\n ) {\n authStrategies.forEach(st => builder.addAuthStrategy(st.key, st.strategy));\n }\n\n getAuthenticationStrategies() {\n return this.authStrategies;\n }\n\n addAuthStrategy(key: string, authStrategy: AuthenticationStrategy) {\n this.authStrategies.push({ key, strategy: authStrategy });\n }\n}\n\n/**\n * This is the backend plugin that provides the Kubernetes integration.\n * @public\n */\nexport const kubernetesPlugin = createBackendPlugin({\n pluginId: 'kubernetes',\n register(env) {\n const extPointObjectsProvider = new ObjectsProvider();\n const extPointClusterSuplier = new ClusterSuplier();\n const extPointAuthStrategy = new AuthStrategy();\n const extPointFetcher = new Fetcher();\n const extPointServiceLocator = new ServiceLocator();\n\n env.registerExtensionPoint(\n kubernetesObjectsProviderExtensionPoint,\n extPointObjectsProvider,\n );\n env.registerExtensionPoint(\n kubernetesClusterSupplierExtensionPoint,\n extPointClusterSuplier,\n );\n env.registerExtensionPoint(\n kubernetesAuthStrategyExtensionPoint,\n extPointAuthStrategy,\n );\n env.registerExtensionPoint(\n kubernetesFetcherExtensionPoint,\n extPointFetcher,\n );\n env.registerExtensionPoint(\n kubernetesServiceLocatorExtensionPoint,\n extPointServiceLocator,\n );\n\n env.registerInit({\n deps: {\n http: coreServices.httpRouter,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n catalogApi: catalogServiceRef,\n permissions: coreServices.permissions,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n },\n async init({\n http,\n logger,\n config,\n discovery,\n catalogApi,\n permissions,\n auth,\n httpAuth,\n }) {\n if (config.has('kubernetes')) {\n // TODO: expose all of the customization & extension points of the builder here\n const builder: KubernetesBuilder = KubernetesBuilder.createBuilder({\n logger,\n config,\n catalogApi,\n permissions,\n discovery,\n auth,\n httpAuth,\n })\n .setObjectsProvider(extPointObjectsProvider.getObjectsProvider())\n .setClusterSupplier(extPointClusterSuplier.getClusterSupplier())\n .setFetcher(extPointFetcher.getFetcher())\n .setServiceLocator(extPointServiceLocator.getServiceLocator());\n\n AuthStrategy.addAuthStrategiesFromArray(\n extPointAuthStrategy.getAuthenticationStrategies(),\n builder,\n );\n const { router } = await builder.build();\n http.use(router);\n } else {\n logger.warn(\n 'Failed to initialize kubernetes backend: valid kubernetes config is missing',\n );\n }\n },\n });\n },\n});\n"],"names":["createBackendPlugin","kubernetesObjectsProviderExtensionPoint","kubernetesClusterSupplierExtensionPoint","kubernetesAuthStrategyExtensionPoint","kubernetesFetcherExtensionPoint","kubernetesServiceLocatorExtensionPoint","coreServices","catalogServiceRef","KubernetesBuilder"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 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 coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\n\nimport {\n type AuthenticationStrategy,\n kubernetesAuthStrategyExtensionPoint,\n type KubernetesAuthStrategyExtensionPoint,\n type KubernetesClustersSupplier,\n kubernetesClusterSupplierExtensionPoint,\n type KubernetesClusterSupplierExtensionPoint,\n KubernetesClusterSupplierFactory,\n type KubernetesFetcher,\n kubernetesFetcherExtensionPoint,\n type KubernetesFetcherExtensionPoint,\n KubernetesFetcherFactory,\n type KubernetesObjectsProvider,\n kubernetesObjectsProviderExtensionPoint,\n type KubernetesObjectsProviderExtensionPoint,\n KubernetesObjectsProviderFactory,\n type KubernetesServiceLocator,\n kubernetesServiceLocatorExtensionPoint,\n type KubernetesServiceLocatorExtensionPoint,\n KubernetesServiceLocatorFactory,\n} from '@backstage/plugin-kubernetes-node';\nimport { KubernetesRouter } from './service/KubernetesRouter';\nimport { KubernetesInitializer } from './service/KubernetesInitializer';\n\nclass ObjectsProvider implements KubernetesObjectsProviderExtensionPoint {\n private objectsProvider: KubernetesObjectsProviderFactory | undefined;\n\n getObjectsProvider() {\n return this.objectsProvider;\n }\n\n addObjectsProvider(\n provider: KubernetesObjectsProvider | KubernetesObjectsProviderFactory,\n ) {\n if (this.objectsProvider) {\n throw new Error(\n 'Multiple Kubernetes objects provider is not supported at this time',\n );\n }\n if (typeof provider !== 'function') {\n this.objectsProvider = async () => provider;\n } else {\n this.objectsProvider = provider;\n }\n }\n}\n\nclass ClusterSuplier implements KubernetesClusterSupplierExtensionPoint {\n private clusterSupplier: KubernetesClusterSupplierFactory | undefined;\n\n getClusterSupplier() {\n return this.clusterSupplier;\n }\n\n addClusterSupplier(\n clusterSupplier:\n | KubernetesClustersSupplier\n | KubernetesClusterSupplierFactory,\n ) {\n if (this.clusterSupplier) {\n throw new Error(\n 'Multiple Kubernetes Cluster Suppliers is not supported at this time',\n );\n }\n if (typeof clusterSupplier !== 'function') {\n this.clusterSupplier = async () => clusterSupplier;\n } else {\n this.clusterSupplier = clusterSupplier;\n }\n }\n}\n\nclass Fetcher implements KubernetesFetcherExtensionPoint {\n private fetcher: KubernetesFetcherFactory | undefined;\n\n getFetcher() {\n return this.fetcher;\n }\n\n addFetcher(fetcher: KubernetesFetcher | KubernetesFetcherFactory) {\n if (this.fetcher) {\n throw new Error(\n 'Multiple Kubernetes Fetchers is not supported at this time',\n );\n }\n if (typeof fetcher !== 'function') {\n this.fetcher = async () => fetcher;\n } else {\n this.fetcher = fetcher;\n }\n }\n}\n\nclass ServiceLocator implements KubernetesServiceLocatorExtensionPoint {\n private serviceLocator: KubernetesServiceLocatorFactory | undefined;\n\n getServiceLocator() {\n return this.serviceLocator;\n }\n\n addServiceLocator(\n serviceLocator: KubernetesServiceLocator | KubernetesServiceLocatorFactory,\n ) {\n if (this.serviceLocator) {\n throw new Error(\n 'Multiple Kubernetes Service Locators is not supported at this time',\n );\n }\n\n if (typeof serviceLocator !== 'function') {\n this.serviceLocator = async () => serviceLocator;\n } else {\n this.serviceLocator = serviceLocator;\n }\n }\n}\n\nclass AuthStrategy implements KubernetesAuthStrategyExtensionPoint {\n private authStrategies: Map<string, AuthenticationStrategy> | undefined;\n\n getAuthenticationStrategies() {\n return this.authStrategies;\n }\n\n addAuthStrategy(key: string, authStrategy: AuthenticationStrategy) {\n if (!this.authStrategies) {\n this.authStrategies = new Map<string, AuthenticationStrategy>();\n }\n\n if (key.includes('-')) {\n throw new Error('Strategy name can not include dashes');\n }\n\n this.authStrategies.set(key, authStrategy);\n }\n}\n\n/**\n * This is the backend plugin that provides the Kubernetes integration.\n * @public\n */\nexport const kubernetesPlugin = createBackendPlugin({\n pluginId: 'kubernetes',\n register(env) {\n const extPointObjectsProvider = new ObjectsProvider();\n const extPointClusterSuplier = new ClusterSuplier();\n const extPointAuthStrategy = new AuthStrategy();\n const extPointFetcher = new Fetcher();\n const extPointServiceLocator = new ServiceLocator();\n\n env.registerExtensionPoint(\n kubernetesObjectsProviderExtensionPoint,\n extPointObjectsProvider,\n );\n env.registerExtensionPoint(\n kubernetesClusterSupplierExtensionPoint,\n extPointClusterSuplier,\n );\n env.registerExtensionPoint(\n kubernetesAuthStrategyExtensionPoint,\n extPointAuthStrategy,\n );\n env.registerExtensionPoint(\n kubernetesFetcherExtensionPoint,\n extPointFetcher,\n );\n env.registerExtensionPoint(\n kubernetesServiceLocatorExtensionPoint,\n extPointServiceLocator,\n );\n\n env.registerInit({\n deps: {\n http: coreServices.httpRouter,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n catalog: catalogServiceRef,\n permissions: coreServices.permissions,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n },\n async init({\n http,\n logger,\n config,\n discovery,\n catalog,\n permissions,\n auth,\n httpAuth,\n }) {\n // TODO: this could do with a cleanup and push some of this initalization somewhere else\n if (config.has('kubernetes')) {\n const initializer = KubernetesInitializer.create({\n logger,\n config,\n catalog,\n auth,\n fetcher: extPointFetcher.getFetcher(),\n clusterSupplier: extPointClusterSuplier.getClusterSupplier(),\n serviceLocator: extPointServiceLocator.getServiceLocator(),\n objectsProvider: extPointObjectsProvider.getObjectsProvider(),\n authStrategyMap: extPointAuthStrategy.getAuthenticationStrategies(),\n });\n\n const {\n fetcher,\n authStrategyMap,\n clusterSupplier,\n serviceLocator,\n objectsProvider,\n } = await initializer.init();\n\n const router = KubernetesRouter.create({\n logger,\n config,\n catalog,\n permissions,\n discovery,\n auth,\n httpAuth,\n authStrategyMap: Object.fromEntries(authStrategyMap.entries()),\n fetcher,\n clusterSupplier,\n serviceLocator,\n objectsProvider,\n });\n\n http.use(await router.getRouter());\n } else {\n logger.warn(\n 'Failed to initialize kubernetes backend: valid kubernetes config is missing',\n );\n }\n },\n });\n },\n});\n"],"names":["createBackendPlugin","kubernetesObjectsProviderExtensionPoint","kubernetesClusterSupplierExtensionPoint","kubernetesAuthStrategyExtensionPoint","kubernetesFetcherExtensionPoint","kubernetesServiceLocatorExtensionPoint","coreServices","catalogServiceRef","KubernetesInitializer","KubernetesRouter"],"mappings":"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"}
@@ -5,7 +5,7 @@ var errors = require('@backstage/errors');
5
5
  var requirePermission = require('../auth/requirePermission.cjs.js');
6
6
  var pluginKubernetesCommon = require('@backstage/plugin-kubernetes-common');
7
7
 
8
- const addResourceRoutesToRouter = (router, catalogApi, objectsProvider, auth, httpAuth, permissionApi) => {
8
+ const addResourceRoutesToRouter = (router, catalog, objectsProvider, httpAuth, permissionApi) => {
9
9
  const getEntityByReq = async (req) => {
10
10
  const rawEntityRef = req.body.entityRef;
11
11
  if (rawEntityRef && typeof rawEntityRef !== "string") {
@@ -19,11 +19,9 @@ const addResourceRoutesToRouter = (router, catalogApi, objectsProvider, auth, ht
19
19
  } catch (error) {
20
20
  throw new errors.InputError(`Invalid entity ref, ${error}`);
21
21
  }
22
- const { token } = await auth.getPluginRequestToken({
23
- onBehalfOf: await httpAuth.credentials(req),
24
- targetPluginId: "catalog"
22
+ const entity = await catalog.getEntityByRef(entityRef, {
23
+ credentials: await httpAuth.credentials(req)
25
24
  });
26
- const entity = await catalogApi.getEntityByRef(entityRef, { token });
27
25
  if (!entity) {
28
26
  throw new errors.InputError(
29
27
  `Entity ref missing, ${catalogModel.stringifyEntityRef(entityRef)}`
@@ -1 +1 @@
1
- {"version":3,"file":"resourcesRoutes.cjs.js","sources":["../../src/routes/resourcesRoutes.ts"],"sourcesContent":["/*\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 {\n CompoundEntityRef,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { InputError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node';\nimport { AuthService, HttpAuthService } from '@backstage/backend-plugin-api';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport { requirePermission } from '../auth/requirePermission';\nimport { kubernetesResourcesReadPermission } from '@backstage/plugin-kubernetes-common';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalogApi: CatalogApi,\n objectsProvider: KubernetesObjectsProvider,\n auth: AuthService,\n httpAuth: HttpAuthService,\n permissionApi: PermissionEvaluator,\n) => {\n const getEntityByReq = async (req: Request<any>) => {\n const rawEntityRef = req.body.entityRef;\n if (rawEntityRef && typeof rawEntityRef !== 'string') {\n throw new InputError(`entity query must be a string`);\n } else if (!rawEntityRef) {\n throw new InputError('entity is a required field');\n }\n let entityRef: CompoundEntityRef | undefined = undefined;\n\n try {\n entityRef = parseEntityRef(rawEntityRef);\n } catch (error) {\n throw new InputError(`Invalid entity ref, ${error}`);\n }\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n });\n\n const entity = await catalogApi.getEntityByRef(entityRef, { token });\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n await requirePermission(\n permissionApi,\n kubernetesResourcesReadPermission,\n httpAuth,\n req,\n );\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity(\n {\n entity,\n auth: req.body.auth,\n },\n { credentials: await httpAuth.credentials(req) },\n );\n res.json(response);\n });\n\n router.post('/resources/custom/query', async (req, res) => {\n await requirePermission(\n permissionApi,\n kubernetesResourcesReadPermission,\n httpAuth,\n req,\n );\n const entity = await getEntityByReq(req);\n\n if (!req.body.customResources) {\n throw new InputError('customResources is a required field');\n } else if (!Array.isArray(req.body.customResources)) {\n throw new InputError('customResources must be an array');\n } else if (req.body.customResources.length === 0) {\n throw new InputError('at least 1 customResource is required');\n }\n\n const response = await objectsProvider.getCustomResourcesByEntity(\n {\n entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n },\n { credentials: await httpAuth.credentials(req) },\n );\n res.json(response);\n });\n};\n"],"names":["InputError","parseEntityRef","stringifyEntityRef","requirePermission","kubernetesResourcesReadPermission"],"mappings":"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"}
1
+ {"version":3,"file":"resourcesRoutes.cjs.js","sources":["../../src/routes/resourcesRoutes.ts"],"sourcesContent":["/*\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 {\n CompoundEntityRef,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { InputError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node';\nimport { HttpAuthService } from '@backstage/backend-plugin-api';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport { requirePermission } from '../auth/requirePermission';\nimport { kubernetesResourcesReadPermission } from '@backstage/plugin-kubernetes-common';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalog: CatalogService,\n objectsProvider: KubernetesObjectsProvider,\n httpAuth: HttpAuthService,\n permissionApi: PermissionEvaluator,\n) => {\n const getEntityByReq = async (req: Request<any>) => {\n const rawEntityRef = req.body.entityRef;\n if (rawEntityRef && typeof rawEntityRef !== 'string') {\n throw new InputError(`entity query must be a string`);\n } else if (!rawEntityRef) {\n throw new InputError('entity is a required field');\n }\n let entityRef: CompoundEntityRef | undefined = undefined;\n\n try {\n entityRef = parseEntityRef(rawEntityRef);\n } catch (error) {\n throw new InputError(`Invalid entity ref, ${error}`);\n }\n\n const entity = await catalog.getEntityByRef(entityRef, {\n credentials: await httpAuth.credentials(req),\n });\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n await requirePermission(\n permissionApi,\n kubernetesResourcesReadPermission,\n httpAuth,\n req,\n );\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity(\n {\n entity,\n auth: req.body.auth,\n },\n { credentials: await httpAuth.credentials(req) },\n );\n res.json(response);\n });\n\n router.post('/resources/custom/query', async (req, res) => {\n await requirePermission(\n permissionApi,\n kubernetesResourcesReadPermission,\n httpAuth,\n req,\n );\n const entity = await getEntityByReq(req);\n\n if (!req.body.customResources) {\n throw new InputError('customResources is a required field');\n } else if (!Array.isArray(req.body.customResources)) {\n throw new InputError('customResources must be an array');\n } else if (req.body.customResources.length === 0) {\n throw new InputError('at least 1 customResource is required');\n }\n\n const response = await objectsProvider.getCustomResourcesByEntity(\n {\n entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n },\n { credentials: await httpAuth.credentials(req) },\n );\n res.json(response);\n });\n};\n"],"names":["InputError","parseEntityRef","stringifyEntityRef","requirePermission","kubernetesResourcesReadPermission"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"KubernetesFanOutHandler.cjs.js","sources":["../../src/service/KubernetesFanOutHandler.ts"],"sourcesContent":["/*\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 {\n KubernetesObjectsProviderOptions,\n ObjectsByEntityRequest,\n} from '../types/types';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n CustomResourceMatcher,\n FetchResponse,\n KUBERNETES_ANNOTATION,\n KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION,\n KubernetesRequestAuth,\n ObjectsByEntityResponse,\n PodFetchResponse,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport type {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\nimport {\n AuthenticationStrategy,\n ClusterDetails,\n CustomResource,\n CustomResourcesByEntity,\n FetchResponseWrapper,\n KubernetesCredential,\n KubernetesFetcher,\n KubernetesObjectsByEntity,\n KubernetesObjectsProvider,\n KubernetesServiceLocator,\n ObjectToFetch,\n} from '@backstage/plugin-kubernetes-node';\nimport {\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/**\n *\n * @public\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: '',\n apiVersion: 'v1',\n plural: 'resourcequotas',\n objectType: 'resourcequotas',\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: 'v2',\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 group: 'apps',\n apiVersion: 'v1',\n plural: 'daemonsets',\n objectType: 'daemonsets',\n },\n];\n\nexport const ALL_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'secrets',\n objectType: 'secrets',\n },\n ...DEFAULT_OBJECTS,\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {\n authStrategy: AuthenticationStrategy;\n}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods' ||\n (fr.type === 'customresources' &&\n fr.resources.length > 0 &&\n fr.resources[0].apiVersion === 'v1' &&\n fr.resources[0].kind === 'Pod');\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: PodStatusFetchResponse[],\n): ClientPodStatus[] => {\n return podMetrics\n .map(r => r.resources)\n .flat()\n .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, PodStatusFetchResponse[]];\n\nexport class KubernetesFanOutHandler implements KubernetesObjectsProvider {\n private readonly logger: LoggerService;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authStrategy: AuthenticationStrategy;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n authStrategy,\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.authStrategy = authStrategy;\n }\n\n async getCustomResourcesByEntity(\n { entity, auth, customResources }: CustomResourcesByEntity,\n options: { credentials: BackstageCredentials },\n ): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n { credentials: options.credentials },\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity(\n { entity, auth }: KubernetesObjectsByEntity,\n options: { credentials: BackstageCredentials },\n ): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(\n entity,\n auth,\n {\n credentials: options.credentials,\n },\n this.objectTypesToFetch,\n );\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n options: { credentials: BackstageCredentials },\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 { clusters } = await this.serviceLocator.getClustersByEntity(entity, {\n objectTypesToFetch: objectTypesToFetch,\n customResources: customResources ?? [],\n credentials: options.credentials,\n });\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusters\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION\n ] || `${KUBERNETES_ANNOTATION}=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusters.map(async clusterDetails => {\n const credential = await this.authStrategy.getCredential(\n clusterDetails,\n auth,\n );\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails,\n credential,\n objectTypesToFetch,\n labelSelector,\n customResources: (\n customResources ||\n clusterDetails.customResources ||\n this.customResources\n ).map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result =>\n this.getMetricsForPods(\n clusterDetails,\n credential,\n labelSelector,\n result,\n ),\n )\n .catch(\n (e): Promise<responseWithMetrics> =>\n e.name === 'FetchError'\n ? Promise.resolve([\n {\n errors: [\n { errorType: 'FETCH_ERROR', message: e.message },\n ],\n responses: [],\n },\n [],\n ])\n : Promise.reject(e),\n )\n .then(r => this.toClusterObjects(clusterDetails, 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 ...(clusterDetails.title && { title: clusterDetails.title }),\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 credential: KubernetesCredential,\n labelSelector: string,\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 if (namespaces.size === 0) {\n return [result, []];\n }\n\n const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces(\n clusterDetails,\n credential,\n namespaces,\n labelSelector,\n );\n\n result.errors.push(...podMetrics.errors);\n return [result, podMetrics.responses as PodStatusFetchResponse[]];\n }\n}\n"],"names":["KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION","KUBERNETES_ANNOTATION"],"mappings":"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"}
1
+ {"version":3,"file":"KubernetesFanOutHandler.cjs.js","sources":["../../src/service/KubernetesFanOutHandler.ts"],"sourcesContent":["/*\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 {\n KubernetesObjectsProviderOptions,\n ObjectsByEntityRequest,\n} from '../types/types';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n CustomResourceMatcher,\n FetchResponse,\n KUBERNETES_ANNOTATION,\n KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION,\n KubernetesRequestAuth,\n ObjectsByEntityResponse,\n PodFetchResponse,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport type {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\nimport {\n AuthenticationStrategy,\n ClusterDetails,\n CustomResource,\n CustomResourcesByEntity,\n FetchResponseWrapper,\n KubernetesCredential,\n KubernetesFetcher,\n KubernetesObjectsByEntity,\n KubernetesObjectsProvider,\n KubernetesServiceLocator,\n ObjectToFetch,\n} from '@backstage/plugin-kubernetes-node';\nimport {\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/**\n *\n * @public\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: '',\n apiVersion: 'v1',\n plural: 'resourcequotas',\n objectType: 'resourcequotas',\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: 'v2',\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 group: 'apps',\n apiVersion: 'v1',\n plural: 'daemonsets',\n objectType: 'daemonsets',\n },\n];\n\nexport const ALL_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'secrets',\n objectType: 'secrets',\n },\n ...DEFAULT_OBJECTS,\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {\n authStrategy: AuthenticationStrategy;\n}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods' ||\n (fr.type === 'customresources' &&\n fr.resources.length > 0 &&\n fr.resources[0].apiVersion === 'v1' &&\n fr.resources[0].kind === 'Pod');\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: PodStatusFetchResponse[],\n): ClientPodStatus[] => {\n return podMetrics\n .map(r => r.resources)\n .flat()\n .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, PodStatusFetchResponse[]];\n\nexport class KubernetesFanOutHandler implements KubernetesObjectsProvider {\n private readonly logger: LoggerService;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authStrategy: AuthenticationStrategy;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n authStrategy,\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.authStrategy = authStrategy;\n }\n\n async getCustomResourcesByEntity(\n { entity, auth, customResources }: CustomResourcesByEntity,\n options: { credentials: BackstageCredentials },\n ): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n { credentials: options.credentials },\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity(\n { entity, auth }: KubernetesObjectsByEntity,\n options: { credentials: BackstageCredentials },\n ): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(\n entity,\n auth,\n {\n credentials: options.credentials,\n },\n this.objectTypesToFetch,\n );\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n options: { credentials: BackstageCredentials },\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 { clusters } = await this.serviceLocator.getClustersByEntity(entity, {\n objectTypesToFetch: objectTypesToFetch,\n customResources: customResources ?? [],\n credentials: options.credentials,\n });\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusters\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION\n ] || `${KUBERNETES_ANNOTATION}=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusters.map(async clusterDetails => {\n const credential = await this.authStrategy.getCredential(\n clusterDetails,\n auth,\n );\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails,\n credential,\n objectTypesToFetch,\n labelSelector,\n customResources: (\n customResources ||\n clusterDetails.customResources ||\n this.customResources\n ).map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result =>\n this.getMetricsForPods(\n clusterDetails,\n credential,\n labelSelector,\n result,\n ),\n )\n .catch(\n (e): Promise<responseWithMetrics> =>\n e.name === 'FetchError'\n ? Promise.resolve([\n {\n errors: [\n { errorType: 'FETCH_ERROR', message: e.message },\n ],\n responses: [],\n },\n [],\n ])\n : Promise.reject(e),\n )\n .then(r => this.toClusterObjects(clusterDetails, 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 ...(clusterDetails.title && { title: clusterDetails.title }),\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 credential: KubernetesCredential,\n labelSelector: string,\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 if (namespaces.size === 0) {\n return [result, []];\n }\n\n const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces(\n clusterDetails,\n credential,\n namespaces,\n labelSelector,\n );\n\n result.errors.push(...podMetrics.errors);\n return [result, podMetrics.responses as PodStatusFetchResponse[]];\n }\n}\n"],"names":["KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION","KUBERNETES_ANNOTATION"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"KubernetesFetcher.cjs.js","sources":["../../src/service/KubernetesFetcher.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 type { Cluster, CoreV1Api, Metrics } from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport {\n FetchResponseWrapper,\n KubernetesFetcher,\n ObjectFetchParams,\n} from '@backstage/plugin-kubernetes-node';\nimport {\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n SERVICEACCOUNT_CA_PATH,\n FetchResponse,\n KubernetesErrorTypes,\n KubernetesFetchError,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport fetch, { RequestInit, Response } from 'node-fetch';\nimport * as https from 'https';\nimport fs from 'fs-extra';\nimport { JsonObject } from '@backstage/types';\nimport {\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport interface KubernetesClientBasedFetcherOptions {\n logger: LoggerService;\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 404:\n return 'NOT_FOUND';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly logger: LoggerService;\n\n constructor({ logger }: KubernetesClientBasedFetcherOptions) {\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(({ objectType, group, apiVersion, plural }) =>\n this.fetchResource(\n params.clusterDetails,\n params.credential,\n group,\n apiVersion,\n plural,\n params.namespace,\n params.labelSelector,\n ).then(\n (r: Response): Promise<FetchResult> =>\n r.ok\n ? r.json().then(\n ({ kind, items }): FetchResponse => ({\n type: objectType,\n resources:\n objectType === 'customresources'\n ? items.map((item: JsonObject) => ({\n ...item,\n kind: kind.replace(/(List)$/, ''),\n }))\n : items,\n }),\n )\n : this.handleUnsuccessfulResponse(params.clusterDetails.name, r),\n ),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n async fetchPodMetricsByNamespaces(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n namespaces: Set<string>,\n labelSelector?: string,\n ): Promise<FetchResponseWrapper> {\n const { topPods } = await import('@kubernetes/client-node');\n\n const fetchResults = Array.from(namespaces).map(async ns => {\n const [podMetrics, podList] = await Promise.all([\n this.fetchResource(\n clusterDetails,\n credential,\n 'metrics.k8s.io',\n 'v1beta1',\n 'pods',\n ns,\n labelSelector,\n ),\n this.fetchResource(\n clusterDetails,\n credential,\n '',\n 'v1',\n 'pods',\n ns,\n labelSelector,\n ),\n ]);\n if (podMetrics.ok && podList.ok) {\n return topPods(\n {\n listPodForAllNamespaces: () => podList.json(),\n } as unknown as CoreV1Api,\n {\n getPodMetrics: () => podMetrics.json(),\n } as unknown as Metrics,\n ).then(\n (resources): PodStatusFetchResponse => ({\n type: 'podstatus',\n resources,\n }),\n );\n } else if (podMetrics.ok) {\n return this.handleUnsuccessfulResponse(clusterDetails.name, podList);\n }\n return this.handleUnsuccessfulResponse(clusterDetails.name, podMetrics);\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n private async handleUnsuccessfulResponse(\n clusterName: string,\n res: Response,\n ): Promise<KubernetesFetchError> {\n const resourcePath = new URL(res.url).pathname;\n this.logger.warn(\n `Received ${\n res.status\n } status when fetching \"${resourcePath}\" from cluster \"${clusterName}\"; body=[${await res.text()}]`,\n );\n return {\n errorType: statusCodeToErrorType(res.status),\n statusCode: res.status,\n resourcePath,\n };\n }\n\n private async fetchResource(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n group: string,\n apiVersion: string,\n plural: string,\n namespace?: string,\n labelSelector?: string,\n ): Promise<Response> {\n const encode = (s: string) => encodeURIComponent(s);\n let resourcePath = group\n ? `/apis/${encode(group)}/${encode(apiVersion)}`\n : `/api/${encode(apiVersion)}`;\n if (namespace) {\n resourcePath += `/namespaces/${encode(namespace)}`;\n }\n resourcePath += `/${encode(plural)}`;\n\n let url: URL;\n let requestInit: RequestInit;\n const authProvider =\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AUTH_PROVIDER];\n\n if (this.isServiceAccountAuthentication(authProvider, clusterDetails)) {\n [url, requestInit] = await this.fetchArgsInCluster(credential);\n } else if (!this.isCredentialMissing(authProvider, credential)) {\n [url, requestInit] = await this.fetchArgs(clusterDetails, credential);\n } else {\n return Promise.reject(\n new Error(\n `no bearer token or client cert for cluster '${clusterDetails.name}' and not running in Kubernetes`,\n ),\n );\n }\n\n if (url.pathname === '/') {\n url.pathname = resourcePath;\n } else {\n url.pathname += resourcePath;\n }\n\n if (labelSelector) {\n url.search = `labelSelector=${encode(labelSelector)}`;\n }\n\n return fetch(url, requestInit);\n }\n\n private isServiceAccountAuthentication(\n authProvider: string,\n clusterDetails: ClusterDetails,\n ) {\n return (\n authProvider === 'serviceAccount' &&\n !clusterDetails.authMetadata.serviceAccountToken &&\n fs.pathExistsSync(SERVICEACCOUNT_CA_PATH)\n );\n }\n\n private isCredentialMissing(\n authProvider: string,\n credential: KubernetesCredential,\n ) {\n return (\n authProvider !== 'localKubectlProxy' && credential.type === 'anonymous'\n );\n }\n\n private async fetchArgs(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n ): Promise<[URL, fetch.RequestInit]> {\n const { bufferFromFileOrString } = await import('@kubernetes/client-node');\n\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n ...(credential.type === 'bearer token' && {\n Authorization: `Bearer ${credential.token}`,\n }),\n },\n };\n\n const url: URL = new URL(clusterDetails.url);\n if (url.protocol === 'https:') {\n requestInit.agent = new https.Agent({\n ca:\n bufferFromFileOrString(\n clusterDetails.caFile,\n clusterDetails.caData,\n ) ?? undefined,\n rejectUnauthorized: !clusterDetails.skipTLSVerify,\n ...(credential.type === 'x509 client certificate' && {\n cert: credential.cert,\n key: credential.key,\n }),\n });\n }\n return [url, requestInit];\n }\n\n private async fetchArgsInCluster(\n credential: KubernetesCredential,\n ): Promise<[URL, fetch.RequestInit]> {\n const { KubeConfig } = await import('@kubernetes/client-node');\n\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n ...(credential.type === 'bearer token' && {\n Authorization: `Bearer ${credential.token}`,\n }),\n },\n };\n\n const kc = new KubeConfig();\n kc.loadFromCluster();\n // loadFromCluster is guaranteed to populate the cluster/user/context\n const cluster = kc.getCurrentCluster() as Cluster;\n\n const url = new URL(cluster.server);\n if (url.protocol === 'https:') {\n requestInit.agent = new https.Agent({\n ca: fs.readFileSync(cluster.caFile as string),\n });\n }\n return [url, requestInit];\n }\n}\n"],"names":["lodash","ANNOTATION_KUBERNETES_AUTH_PROVIDER","fetch","fs","SERVICEACCOUNT_CA_PATH","https"],"mappings":"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"}
1
+ {"version":3,"file":"KubernetesFetcher.cjs.js","sources":["../../src/service/KubernetesFetcher.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 type { Cluster, CoreV1Api, Metrics } from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport {\n FetchResponseWrapper,\n KubernetesFetcher,\n ObjectFetchParams,\n} from '@backstage/plugin-kubernetes-node';\nimport {\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n SERVICEACCOUNT_CA_PATH,\n FetchResponse,\n KubernetesErrorTypes,\n KubernetesFetchError,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport fetch, { RequestInit, Response } from 'node-fetch';\nimport * as https from 'https';\nimport fs from 'fs-extra';\nimport { JsonObject } from '@backstage/types';\nimport {\n ClusterDetails,\n KubernetesCredential,\n} from '@backstage/plugin-kubernetes-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport interface KubernetesClientBasedFetcherOptions {\n logger: LoggerService;\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 404:\n return 'NOT_FOUND';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly logger: LoggerService;\n\n constructor({ logger }: KubernetesClientBasedFetcherOptions) {\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(({ objectType, group, apiVersion, plural }) =>\n this.fetchResource(\n params.clusterDetails,\n params.credential,\n group,\n apiVersion,\n plural,\n params.namespace,\n params.labelSelector,\n ).then(\n (r: Response): Promise<FetchResult> =>\n r.ok\n ? r.json().then(\n ({ kind, items }): FetchResponse => ({\n type: objectType,\n resources:\n objectType === 'customresources'\n ? items.map((item: JsonObject) => ({\n ...item,\n kind: kind.replace(/(List)$/, ''),\n }))\n : items,\n }),\n )\n : this.handleUnsuccessfulResponse(params.clusterDetails.name, r),\n ),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n async fetchPodMetricsByNamespaces(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n namespaces: Set<string>,\n labelSelector?: string,\n ): Promise<FetchResponseWrapper> {\n const { topPods } = await import('@kubernetes/client-node');\n\n const fetchResults = Array.from(namespaces).map(async ns => {\n const [podMetrics, podList] = await Promise.all([\n this.fetchResource(\n clusterDetails,\n credential,\n 'metrics.k8s.io',\n 'v1beta1',\n 'pods',\n ns,\n labelSelector,\n ),\n this.fetchResource(\n clusterDetails,\n credential,\n '',\n 'v1',\n 'pods',\n ns,\n labelSelector,\n ),\n ]);\n if (podMetrics.ok && podList.ok) {\n return topPods(\n {\n listPodForAllNamespaces: () => podList.json(),\n } as unknown as CoreV1Api,\n {\n getPodMetrics: () => podMetrics.json(),\n } as unknown as Metrics,\n ).then(\n (resources): PodStatusFetchResponse => ({\n type: 'podstatus',\n resources,\n }),\n );\n } else if (podMetrics.ok) {\n return this.handleUnsuccessfulResponse(clusterDetails.name, podList);\n }\n return this.handleUnsuccessfulResponse(clusterDetails.name, podMetrics);\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n private async handleUnsuccessfulResponse(\n clusterName: string,\n res: Response,\n ): Promise<KubernetesFetchError> {\n const resourcePath = new URL(res.url).pathname;\n this.logger.warn(\n `Received ${\n res.status\n } status when fetching \"${resourcePath}\" from cluster \"${clusterName}\"; body=[${await res.text()}]`,\n );\n return {\n errorType: statusCodeToErrorType(res.status),\n statusCode: res.status,\n resourcePath,\n };\n }\n\n private async fetchResource(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n group: string,\n apiVersion: string,\n plural: string,\n namespace?: string,\n labelSelector?: string,\n ): Promise<Response> {\n const encode = (s: string) => encodeURIComponent(s);\n let resourcePath = group\n ? `/apis/${encode(group)}/${encode(apiVersion)}`\n : `/api/${encode(apiVersion)}`;\n if (namespace) {\n resourcePath += `/namespaces/${encode(namespace)}`;\n }\n resourcePath += `/${encode(plural)}`;\n\n let url: URL;\n let requestInit: RequestInit;\n const authProvider =\n clusterDetails.authMetadata[ANNOTATION_KUBERNETES_AUTH_PROVIDER];\n\n if (this.isServiceAccountAuthentication(authProvider, clusterDetails)) {\n [url, requestInit] = await this.fetchArgsInCluster(credential);\n } else if (!this.isCredentialMissing(authProvider, credential)) {\n [url, requestInit] = await this.fetchArgs(clusterDetails, credential);\n } else {\n return Promise.reject(\n new Error(\n `no bearer token or client cert for cluster '${clusterDetails.name}' and not running in Kubernetes`,\n ),\n );\n }\n\n if (url.pathname === '/') {\n url.pathname = resourcePath;\n } else {\n url.pathname += resourcePath;\n }\n\n if (labelSelector) {\n url.search = `labelSelector=${encode(labelSelector)}`;\n }\n\n return fetch(url, requestInit);\n }\n\n private isServiceAccountAuthentication(\n authProvider: string,\n clusterDetails: ClusterDetails,\n ) {\n return (\n authProvider === 'serviceAccount' &&\n !clusterDetails.authMetadata.serviceAccountToken &&\n fs.pathExistsSync(SERVICEACCOUNT_CA_PATH)\n );\n }\n\n private isCredentialMissing(\n authProvider: string,\n credential: KubernetesCredential,\n ) {\n return (\n authProvider !== 'localKubectlProxy' && credential.type === 'anonymous'\n );\n }\n\n private async fetchArgs(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n ): Promise<[URL, fetch.RequestInit]> {\n const { bufferFromFileOrString } = await import('@kubernetes/client-node');\n\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n ...(credential.type === 'bearer token' && {\n Authorization: `Bearer ${credential.token}`,\n }),\n },\n };\n\n const url: URL = new URL(clusterDetails.url);\n if (url.protocol === 'https:') {\n requestInit.agent = new https.Agent({\n ca:\n bufferFromFileOrString(\n clusterDetails.caFile,\n clusterDetails.caData,\n ) ?? undefined,\n rejectUnauthorized: !clusterDetails.skipTLSVerify,\n ...(credential.type === 'x509 client certificate' && {\n cert: credential.cert,\n key: credential.key,\n }),\n });\n }\n return [url, requestInit];\n }\n\n private async fetchArgsInCluster(\n credential: KubernetesCredential,\n ): Promise<[URL, fetch.RequestInit]> {\n const { KubeConfig } = await import('@kubernetes/client-node');\n\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n ...(credential.type === 'bearer token' && {\n Authorization: `Bearer ${credential.token}`,\n }),\n },\n };\n\n const kc = new KubeConfig();\n kc.loadFromCluster();\n // loadFromCluster is guaranteed to populate the cluster/user/context\n const cluster = kc.getCurrentCluster() as Cluster;\n\n const url = new URL(cluster.server);\n if (url.protocol === 'https:') {\n requestInit.agent = new https.Agent({\n ca: fs.readFileSync(cluster.caFile as string),\n });\n }\n return [url, requestInit];\n }\n}\n"],"names":["lodash","ANNOTATION_KUBERNETES_AUTH_PROVIDER","fetch","fs","SERVICEACCOUNT_CA_PATH","https"],"mappings":"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"}