@backstage/plugin-kubernetes-backend 0.21.4-next.1 → 0.21.5-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @backstage/plugin-kubernetes-backend
|
|
2
2
|
|
|
3
|
+
## 0.21.5-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 998664c: chore(deps): Bump `ws` from 8.20.0 to 8.20.1
|
|
8
|
+
- c4f935b: pool HTTPS agents per cluster in KubernetesFetcher
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
- @backstage/catalog-client@1.16.0-next.0
|
|
11
|
+
- @backstage/plugin-catalog-node@2.2.2-next.0
|
|
12
|
+
- @backstage/plugin-kubernetes-node@0.4.5-next.0
|
|
13
|
+
- @backstage/plugin-permission-node@0.11.1-next.0
|
|
14
|
+
- @backstage/backend-plugin-api@1.9.2-next.0
|
|
15
|
+
|
|
16
|
+
## 0.21.4
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 1ecc3ca: Fixed spelling mistakes in internal code
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
- @backstage/catalog-model@1.9.0
|
|
23
|
+
- @backstage/errors@1.3.1
|
|
24
|
+
- @backstage/integration-aws-node@0.2.0
|
|
25
|
+
- @backstage/backend-plugin-api@1.9.1
|
|
26
|
+
- @backstage/plugin-catalog-node@2.2.1
|
|
27
|
+
- @backstage/plugin-kubernetes-common@0.9.12
|
|
28
|
+
- @backstage/plugin-kubernetes-node@0.4.4
|
|
29
|
+
- @backstage/plugin-permission-node@0.11.0
|
|
30
|
+
- @backstage/plugin-permission-common@0.9.9
|
|
31
|
+
- @backstage/catalog-client@1.15.1
|
|
32
|
+
- @backstage/config@1.3.8
|
|
33
|
+
|
|
3
34
|
## 0.21.4-next.1
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
package/dist/package.json.cjs.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var lodash = require('lodash');
|
|
4
3
|
var pluginKubernetesCommon = require('@backstage/plugin-kubernetes-common');
|
|
5
4
|
var fetch = require('node-fetch');
|
|
6
5
|
var https = require('node:https');
|
|
@@ -26,20 +25,22 @@ function _interopNamespaceCompat(e) {
|
|
|
26
25
|
return Object.freeze(n);
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
var lodash__default = /*#__PURE__*/_interopDefaultCompat(lodash);
|
|
30
28
|
var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch);
|
|
31
29
|
var https__namespace = /*#__PURE__*/_interopNamespaceCompat(https);
|
|
32
30
|
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
33
31
|
|
|
34
32
|
const isError = (fr) => fr.hasOwnProperty("errorType");
|
|
35
33
|
function fetchResultsToResponseWrapper(results) {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
const errors = [];
|
|
35
|
+
const responses = [];
|
|
36
|
+
for (const result of results) {
|
|
37
|
+
if (isError(result)) {
|
|
38
|
+
errors.push(result);
|
|
39
|
+
} else {
|
|
40
|
+
responses.push(result);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { errors, responses };
|
|
43
44
|
}
|
|
44
45
|
const statusCodeToErrorType = (statusCode) => {
|
|
45
46
|
switch (statusCode) {
|
|
@@ -57,6 +58,8 @@ const statusCodeToErrorType = (statusCode) => {
|
|
|
57
58
|
};
|
|
58
59
|
class KubernetesClientBasedFetcher {
|
|
59
60
|
logger;
|
|
61
|
+
agentCache = /* @__PURE__ */ new Map();
|
|
62
|
+
inClusterCache;
|
|
60
63
|
constructor({ logger }) {
|
|
61
64
|
this.logger = logger;
|
|
62
65
|
}
|
|
@@ -65,9 +68,7 @@ class KubernetesClientBasedFetcher {
|
|
|
65
68
|
({ objectType, group, apiVersion, plural }) => this.fetchResource(
|
|
66
69
|
params.clusterDetails,
|
|
67
70
|
params.credential,
|
|
68
|
-
group,
|
|
69
|
-
apiVersion,
|
|
70
|
-
plural,
|
|
71
|
+
{ group, apiVersion, plural },
|
|
71
72
|
params.namespace,
|
|
72
73
|
params.labelSelector
|
|
73
74
|
).then(
|
|
@@ -82,49 +83,53 @@ class KubernetesClientBasedFetcher {
|
|
|
82
83
|
return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);
|
|
83
84
|
}
|
|
84
85
|
async fetchPodMetricsByNamespaces(clusterDetails, credential, namespaces, labelSelector) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"pods",
|
|
94
|
-
ns,
|
|
95
|
-
labelSelector
|
|
96
|
-
),
|
|
97
|
-
this.fetchResource(
|
|
98
|
-
clusterDetails,
|
|
99
|
-
credential,
|
|
100
|
-
"",
|
|
101
|
-
"v1",
|
|
102
|
-
"pods",
|
|
103
|
-
ns,
|
|
104
|
-
labelSelector
|
|
105
|
-
)
|
|
106
|
-
]);
|
|
107
|
-
if (podMetrics.ok && podList.ok) {
|
|
108
|
-
return topPods(
|
|
109
|
-
{
|
|
110
|
-
listPodForAllNamespaces: () => podList.json()
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
getPodMetrics: () => podMetrics.json()
|
|
114
|
-
}
|
|
115
|
-
).then(
|
|
116
|
-
(resources) => ({
|
|
117
|
-
type: "podstatus",
|
|
118
|
-
resources
|
|
119
|
-
})
|
|
120
|
-
);
|
|
121
|
-
} else if (podMetrics.ok) {
|
|
122
|
-
return this.handleUnsuccessfulResponse(clusterDetails.name, podList);
|
|
123
|
-
}
|
|
124
|
-
return this.handleUnsuccessfulResponse(clusterDetails.name, podMetrics);
|
|
125
|
-
});
|
|
86
|
+
const fetchResults = Array.from(namespaces).map(
|
|
87
|
+
(ns) => this.fetchPodMetricsForNamespace(
|
|
88
|
+
clusterDetails,
|
|
89
|
+
credential,
|
|
90
|
+
ns,
|
|
91
|
+
labelSelector
|
|
92
|
+
)
|
|
93
|
+
);
|
|
126
94
|
return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);
|
|
127
95
|
}
|
|
96
|
+
async fetchPodMetricsForNamespace(clusterDetails, credential, namespace, labelSelector) {
|
|
97
|
+
const [podMetrics, podList] = await Promise.all([
|
|
98
|
+
this.fetchResource(
|
|
99
|
+
clusterDetails,
|
|
100
|
+
credential,
|
|
101
|
+
{ group: "metrics.k8s.io", apiVersion: "v1beta1", plural: "pods" },
|
|
102
|
+
namespace,
|
|
103
|
+
labelSelector
|
|
104
|
+
),
|
|
105
|
+
this.fetchResource(
|
|
106
|
+
clusterDetails,
|
|
107
|
+
credential,
|
|
108
|
+
{ group: "", apiVersion: "v1", plural: "pods" },
|
|
109
|
+
namespace,
|
|
110
|
+
labelSelector
|
|
111
|
+
)
|
|
112
|
+
]);
|
|
113
|
+
if (podMetrics.ok && podList.ok) {
|
|
114
|
+
const { topPods } = await import('@kubernetes/client-node');
|
|
115
|
+
return topPods(
|
|
116
|
+
{
|
|
117
|
+
listPodForAllNamespaces: () => podList.json()
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
getPodMetrics: () => podMetrics.json()
|
|
121
|
+
}
|
|
122
|
+
).then(
|
|
123
|
+
(resources) => ({
|
|
124
|
+
type: "podstatus",
|
|
125
|
+
resources
|
|
126
|
+
})
|
|
127
|
+
);
|
|
128
|
+
} else if (podMetrics.ok) {
|
|
129
|
+
return this.handleUnsuccessfulResponse(clusterDetails.name, podList);
|
|
130
|
+
}
|
|
131
|
+
return this.handleUnsuccessfulResponse(clusterDetails.name, podMetrics);
|
|
132
|
+
}
|
|
128
133
|
async handleUnsuccessfulResponse(clusterName, res) {
|
|
129
134
|
const resourcePath = new URL(res.url).pathname;
|
|
130
135
|
this.logger.warn(
|
|
@@ -136,13 +141,22 @@ class KubernetesClientBasedFetcher {
|
|
|
136
141
|
resourcePath
|
|
137
142
|
};
|
|
138
143
|
}
|
|
139
|
-
|
|
144
|
+
buildResourcePath(group, apiVersion, plural, namespace) {
|
|
140
145
|
const encode = (s) => encodeURIComponent(s);
|
|
141
|
-
let
|
|
146
|
+
let path = group ? `/apis/${encode(group)}/${encode(apiVersion)}` : `/api/${encode(apiVersion)}`;
|
|
142
147
|
if (namespace) {
|
|
143
|
-
|
|
148
|
+
path += `/namespaces/${encode(namespace)}`;
|
|
144
149
|
}
|
|
145
|
-
|
|
150
|
+
path += `/${encode(plural)}`;
|
|
151
|
+
return path;
|
|
152
|
+
}
|
|
153
|
+
async fetchResource(clusterDetails, credential, resource, namespace, labelSelector) {
|
|
154
|
+
const resourcePath = this.buildResourcePath(
|
|
155
|
+
resource.group,
|
|
156
|
+
resource.apiVersion,
|
|
157
|
+
resource.plural,
|
|
158
|
+
namespace
|
|
159
|
+
);
|
|
146
160
|
let url;
|
|
147
161
|
let requestInit;
|
|
148
162
|
const authProvider = clusterDetails.authMetadata[pluginKubernetesCommon.ANNOTATION_KUBERNETES_AUTH_PROVIDER];
|
|
@@ -163,7 +177,7 @@ class KubernetesClientBasedFetcher {
|
|
|
163
177
|
url.pathname += resourcePath;
|
|
164
178
|
}
|
|
165
179
|
if (labelSelector) {
|
|
166
|
-
url.search = `labelSelector=${
|
|
180
|
+
url.search = `labelSelector=${encodeURIComponent(labelSelector)}`;
|
|
167
181
|
}
|
|
168
182
|
return fetch__default.default(url, requestInit);
|
|
169
183
|
}
|
|
@@ -173,56 +187,69 @@ class KubernetesClientBasedFetcher {
|
|
|
173
187
|
isCredentialMissing(authProvider, credential) {
|
|
174
188
|
return authProvider !== "localKubectlProxy" && credential.type === "anonymous";
|
|
175
189
|
}
|
|
190
|
+
buildRequestHeaders(credential) {
|
|
191
|
+
return {
|
|
192
|
+
Accept: "application/json",
|
|
193
|
+
"Content-Type": "application/json",
|
|
194
|
+
...credential.type === "bearer token" && {
|
|
195
|
+
Authorization: `Bearer ${credential.token}`
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
176
199
|
async fetchArgs(clusterDetails, credential) {
|
|
177
200
|
const { bufferFromFileOrString } = await import('@kubernetes/client-node');
|
|
178
201
|
const requestInit = {
|
|
179
202
|
method: "GET",
|
|
180
|
-
headers:
|
|
181
|
-
Accept: "application/json",
|
|
182
|
-
"Content-Type": "application/json",
|
|
183
|
-
...credential.type === "bearer token" && {
|
|
184
|
-
Authorization: `Bearer ${credential.token}`
|
|
185
|
-
}
|
|
186
|
-
}
|
|
203
|
+
headers: this.buildRequestHeaders(credential)
|
|
187
204
|
};
|
|
188
205
|
const url = new URL(clusterDetails.url);
|
|
189
206
|
if (url.protocol === "https:") {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
clusterDetails.caFile,
|
|
193
|
-
clusterDetails.caData
|
|
194
|
-
) ?? void 0,
|
|
195
|
-
rejectUnauthorized: !clusterDetails.skipTLSVerify,
|
|
196
|
-
...credential.type === "x509 client certificate" && {
|
|
197
|
-
cert: credential.cert,
|
|
198
|
-
key: credential.key
|
|
199
|
-
}
|
|
200
|
-
});
|
|
207
|
+
const ca = bufferFromFileOrString(clusterDetails.caFile, clusterDetails.caData) ?? void 0;
|
|
208
|
+
requestInit.agent = this.getOrCreateAgent(clusterDetails, credential, ca);
|
|
201
209
|
}
|
|
202
210
|
return [url, requestInit];
|
|
203
211
|
}
|
|
204
212
|
async fetchArgsInCluster(credential) {
|
|
205
|
-
|
|
213
|
+
if (!this.inClusterCache) {
|
|
214
|
+
const { KubeConfig } = await import('@kubernetes/client-node');
|
|
215
|
+
const kc = new KubeConfig();
|
|
216
|
+
kc.loadFromCluster();
|
|
217
|
+
const cluster = kc.getCurrentCluster();
|
|
218
|
+
const url2 = new URL(cluster.server);
|
|
219
|
+
const agent2 = url2.protocol === "https:" ? new https__namespace.Agent({
|
|
220
|
+
ca: fs__default.default.readFileSync(cluster.caFile),
|
|
221
|
+
keepAlive: true
|
|
222
|
+
}) : void 0;
|
|
223
|
+
this.inClusterCache = { url: url2, agent: agent2 };
|
|
224
|
+
}
|
|
225
|
+
const { url, agent } = this.inClusterCache;
|
|
206
226
|
const requestInit = {
|
|
207
227
|
method: "GET",
|
|
208
|
-
headers:
|
|
209
|
-
|
|
210
|
-
"Content-Type": "application/json",
|
|
211
|
-
...credential.type === "bearer token" && {
|
|
212
|
-
Authorization: `Bearer ${credential.token}`
|
|
213
|
-
}
|
|
214
|
-
}
|
|
228
|
+
headers: this.buildRequestHeaders(credential),
|
|
229
|
+
...agent && { agent }
|
|
215
230
|
};
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
231
|
+
return [new URL(url.toString()), requestInit];
|
|
232
|
+
}
|
|
233
|
+
buildAgentCacheKey(clusterDetails, credential) {
|
|
234
|
+
const certPart = credential.type === "x509 client certificate" ? `${credential.cert}|${credential.key}` : "";
|
|
235
|
+
return `${clusterDetails.url}|${clusterDetails.skipTLSVerify ?? false}|${clusterDetails.caData ?? ""}|${clusterDetails.caFile ?? ""}|${certPart}`;
|
|
236
|
+
}
|
|
237
|
+
getOrCreateAgent(clusterDetails, credential, ca) {
|
|
238
|
+
const key = this.buildAgentCacheKey(clusterDetails, credential);
|
|
239
|
+
let agent = this.agentCache.get(key);
|
|
240
|
+
if (!agent) {
|
|
241
|
+
agent = new https__namespace.Agent({
|
|
242
|
+
ca,
|
|
243
|
+
rejectUnauthorized: !clusterDetails.skipTLSVerify,
|
|
244
|
+
keepAlive: true,
|
|
245
|
+
...credential.type === "x509 client certificate" && {
|
|
246
|
+
cert: credential.cert,
|
|
247
|
+
key: credential.key
|
|
248
|
+
}
|
|
223
249
|
});
|
|
250
|
+
this.agentCache.set(key, agent);
|
|
224
251
|
}
|
|
225
|
-
return
|
|
252
|
+
return agent;
|
|
226
253
|
}
|
|
227
254
|
transformResources(objectType, kind, items) {
|
|
228
255
|
if (objectType === "customresources") {
|
|
@@ -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 'node: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: this.transformResources(objectType, kind, 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 private transformResources(\n objectType: string,\n kind: string,\n items: JsonObject[],\n ): JsonObject[] {\n if (objectType === 'customresources') {\n return items.map((item: JsonObject) => ({\n ...item,\n kind: kind.replace(/(List)$/, ''),\n }));\n }\n\n if (objectType === 'secrets') {\n return items.map((item: JsonObject) => {\n if (item.data && typeof item.data === 'object') {\n return {\n ...item,\n data: Object.fromEntries(\n Object.keys(item.data).map(key => [key, '***']),\n ),\n };\n }\n return item;\n });\n }\n\n return items;\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 {\n FetchResponseWrapper,\n KubernetesFetcher,\n ObjectFetchParams,\n ObjectToFetch,\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 'node: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 errors: KubernetesFetchError[] = [];\n const responses: FetchResponse[] = [];\n for (const result of results) {\n if (isError(result)) {\n errors.push(result);\n } else {\n responses.push(result);\n }\n }\n return { errors, responses };\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 private readonly agentCache = new Map<string, https.Agent>();\n private inClusterCache:\n | { url: URL; agent: https.Agent | undefined }\n | undefined;\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, apiVersion, 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: this.transformResources(objectType, kind, 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 fetchResults = Array.from(namespaces).map(ns =>\n this.fetchPodMetricsForNamespace(\n clusterDetails,\n credential,\n ns,\n labelSelector,\n ),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n private async fetchPodMetricsForNamespace(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n namespace: string,\n labelSelector?: string,\n ): Promise<FetchResult> {\n const [podMetrics, podList] = await Promise.all([\n this.fetchResource(\n clusterDetails,\n credential,\n { group: 'metrics.k8s.io', apiVersion: 'v1beta1', plural: 'pods' },\n namespace,\n labelSelector,\n ),\n this.fetchResource(\n clusterDetails,\n credential,\n { group: '', apiVersion: 'v1', plural: 'pods' },\n namespace,\n labelSelector,\n ),\n ]);\n if (podMetrics.ok && podList.ok) {\n const { topPods } = await import('@kubernetes/client-node');\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 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 buildResourcePath(\n group: string,\n apiVersion: string,\n plural: string,\n namespace?: string,\n ): string {\n const encode = (s: string) => encodeURIComponent(s);\n let path = group\n ? `/apis/${encode(group)}/${encode(apiVersion)}`\n : `/api/${encode(apiVersion)}`;\n if (namespace) {\n path += `/namespaces/${encode(namespace)}`;\n }\n path += `/${encode(plural)}`;\n return path;\n }\n\n private async fetchResource(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n resource: Pick<ObjectToFetch, 'group' | 'apiVersion' | 'plural'>,\n namespace?: string,\n labelSelector?: string,\n ): Promise<Response> {\n const resourcePath = this.buildResourcePath(\n resource.group,\n resource.apiVersion,\n resource.plural,\n namespace,\n );\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=${encodeURIComponent(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 buildRequestHeaders(\n credential: KubernetesCredential,\n ): Record<string, string> {\n return {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n ...(credential.type === 'bearer token' && {\n Authorization: `Bearer ${credential.token}`,\n }),\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 const requestInit: RequestInit = {\n method: 'GET',\n headers: this.buildRequestHeaders(credential),\n };\n\n const url: URL = new URL(clusterDetails.url);\n if (url.protocol === 'https:') {\n const ca =\n bufferFromFileOrString(clusterDetails.caFile, clusterDetails.caData) ??\n undefined;\n requestInit.agent = this.getOrCreateAgent(clusterDetails, credential, ca);\n }\n return [url, requestInit];\n }\n\n private async fetchArgsInCluster(\n credential: KubernetesCredential,\n ): Promise<[URL, fetch.RequestInit]> {\n if (!this.inClusterCache) {\n const { KubeConfig } = await import('@kubernetes/client-node');\n const kc = new KubeConfig();\n kc.loadFromCluster();\n const cluster = kc.getCurrentCluster() as Cluster;\n const url = new URL(cluster.server);\n const agent =\n url.protocol === 'https:'\n ? new https.Agent({\n ca: fs.readFileSync(cluster.caFile as string),\n keepAlive: true,\n })\n : undefined;\n this.inClusterCache = { url, agent };\n }\n\n const { url, agent } = this.inClusterCache;\n const requestInit: RequestInit = {\n method: 'GET',\n headers: this.buildRequestHeaders(credential),\n ...(agent && { agent }),\n };\n return [new URL(url.toString()), requestInit];\n }\n\n private buildAgentCacheKey(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n ): string {\n const certPart =\n credential.type === 'x509 client certificate'\n ? `${credential.cert}|${credential.key}`\n : '';\n return `${clusterDetails.url}|${clusterDetails.skipTLSVerify ?? false}|${\n clusterDetails.caData ?? ''\n }|${clusterDetails.caFile ?? ''}|${certPart}`;\n }\n\n private getOrCreateAgent(\n clusterDetails: ClusterDetails,\n credential: KubernetesCredential,\n ca: Buffer | string | undefined,\n ): https.Agent {\n const key = this.buildAgentCacheKey(clusterDetails, credential);\n\n let agent = this.agentCache.get(key);\n if (!agent) {\n agent = new https.Agent({\n ca,\n rejectUnauthorized: !clusterDetails.skipTLSVerify,\n keepAlive: true,\n ...(credential.type === 'x509 client certificate' && {\n cert: credential.cert,\n key: credential.key,\n }),\n });\n this.agentCache.set(key, agent);\n }\n return agent;\n }\n\n private transformResources(\n objectType: string,\n kind: string,\n items: JsonObject[],\n ): JsonObject[] {\n if (objectType === 'customresources') {\n return items.map((item: JsonObject) => ({\n ...item,\n kind: kind.replace(/(List)$/, ''),\n }));\n }\n\n if (objectType === 'secrets') {\n return items.map((item: JsonObject) => {\n if (item.data && typeof item.data === 'object') {\n return {\n ...item,\n data: Object.fromEntries(\n Object.keys(item.data).map(key => [key, '***']),\n ),\n };\n }\n return item;\n });\n }\n\n return items;\n }\n}\n"],"names":["ANNOTATION_KUBERNETES_AUTH_PROVIDER","fetch","fs","SERVICEACCOUNT_CA_PATH","url","agent","https"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-kubernetes-backend",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.5-next.0",
|
|
4
4
|
"description": "A Backstage backend plugin that integrates towards Kubernetes",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "backend-plugin",
|
|
@@ -49,17 +49,17 @@
|
|
|
49
49
|
"@aws-crypto/sha256-js": "^5.0.0",
|
|
50
50
|
"@aws-sdk/credential-providers": "^3.350.0",
|
|
51
51
|
"@azure/identity": "^4.0.0",
|
|
52
|
-
"@backstage/backend-plugin-api": "1.9.
|
|
53
|
-
"@backstage/catalog-client": "1.
|
|
54
|
-
"@backstage/catalog-model": "1.
|
|
55
|
-
"@backstage/config": "1.3.8
|
|
56
|
-
"@backstage/errors": "1.3.1
|
|
57
|
-
"@backstage/integration-aws-node": "0.2.0
|
|
58
|
-
"@backstage/plugin-catalog-node": "2.2.
|
|
59
|
-
"@backstage/plugin-kubernetes-common": "0.9.12
|
|
60
|
-
"@backstage/plugin-kubernetes-node": "0.4.
|
|
61
|
-
"@backstage/plugin-permission-common": "0.9.9
|
|
62
|
-
"@backstage/plugin-permission-node": "0.
|
|
52
|
+
"@backstage/backend-plugin-api": "1.9.2-next.0",
|
|
53
|
+
"@backstage/catalog-client": "1.16.0-next.0",
|
|
54
|
+
"@backstage/catalog-model": "1.9.0",
|
|
55
|
+
"@backstage/config": "1.3.8",
|
|
56
|
+
"@backstage/errors": "1.3.1",
|
|
57
|
+
"@backstage/integration-aws-node": "0.2.0",
|
|
58
|
+
"@backstage/plugin-catalog-node": "2.2.2-next.0",
|
|
59
|
+
"@backstage/plugin-kubernetes-common": "0.9.12",
|
|
60
|
+
"@backstage/plugin-kubernetes-node": "0.4.5-next.0",
|
|
61
|
+
"@backstage/plugin-permission-common": "0.9.9",
|
|
62
|
+
"@backstage/plugin-permission-node": "0.11.1-next.0",
|
|
63
63
|
"@backstage/types": "1.2.2",
|
|
64
64
|
"@google-cloud/container": "^5.0.0",
|
|
65
65
|
"@jest-mock/express": "^2.0.1",
|
|
@@ -75,15 +75,15 @@
|
|
|
75
75
|
"node-fetch": "^2.7.0"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
|
-
"@backstage/backend-defaults": "0.17.
|
|
79
|
-
"@backstage/backend-test-utils": "1.11.
|
|
80
|
-
"@backstage/cli": "0.36.
|
|
81
|
-
"@backstage/plugin-permission-backend": "0.7.
|
|
82
|
-
"@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.
|
|
78
|
+
"@backstage/backend-defaults": "0.17.2-next.0",
|
|
79
|
+
"@backstage/backend-test-utils": "1.11.4-next.0",
|
|
80
|
+
"@backstage/cli": "0.36.3-next.0",
|
|
81
|
+
"@backstage/plugin-permission-backend": "0.7.13-next.0",
|
|
82
|
+
"@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.20-next.0",
|
|
83
83
|
"@types/express": "^4.17.6",
|
|
84
84
|
"msw": "^1.0.0",
|
|
85
85
|
"supertest": "^7.0.0",
|
|
86
|
-
"ws": "^8.
|
|
86
|
+
"ws": "^8.20.1"
|
|
87
87
|
},
|
|
88
88
|
"configSchema": "config.d.ts",
|
|
89
89
|
"typesVersions": {
|