@backstage/plugin-kubernetes-backend 0.10.0-next.1 → 0.10.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/alpha/package.json +1 -1
- package/dist/index.cjs.js +72 -62
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +46 -13
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @backstage/plugin-kubernetes-backend
|
|
2
2
|
|
|
3
|
+
## 0.10.0-next.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e6c7c850129: Plugins that instantiate the `KubernetesProxy` must now provide a parameter of the type `KubernetesProxyOptions` which includes providing a `KubernetesAuthTranslator`. The `KubernetesBuilder` now builds its own `KubernetesAuthTranslatorMap` that it provides to the `KubernetesProxy`. The `DispatchingKubernetesAuthTranslator` expects a `KubernetesTranslatorMap` to be provided as a parameter. The `KubernetesBuilder` now has a method called `setAuthTranslatorMap` which allows integrators to bring their own `KubernetesAuthTranslator's` to the `KubernetesPlugin`.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 76e8f08fa24: fix localKubectlProxy auth provider fetching
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
- @backstage/backend-common@0.18.4-next.2
|
|
14
|
+
- @backstage/catalog-client@1.4.1-next.0
|
|
15
|
+
- @backstage/plugin-permission-node@0.7.7-next.2
|
|
16
|
+
- @backstage/backend-plugin-api@0.5.1-next.2
|
|
17
|
+
- @backstage/catalog-model@1.2.1
|
|
18
|
+
- @backstage/config@1.0.7
|
|
19
|
+
- @backstage/errors@1.1.5
|
|
20
|
+
- @backstage/plugin-auth-node@0.2.13-next.2
|
|
21
|
+
- @backstage/plugin-catalog-node@1.3.5-next.2
|
|
22
|
+
- @backstage/plugin-kubernetes-common@0.6.2-next.1
|
|
23
|
+
- @backstage/plugin-permission-common@0.7.5-next.0
|
|
24
|
+
|
|
3
25
|
## 0.10.0-next.1
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/alpha/package.json
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -223,6 +223,20 @@ class GoogleServiceAccountAuthTranslator {
|
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
class DispatchingKubernetesAuthTranslator {
|
|
227
|
+
constructor(options) {
|
|
228
|
+
this.translatorMap = options.authTranslatorMap;
|
|
229
|
+
}
|
|
230
|
+
decorateClusterDetailsWithAuth(clusterDetails, auth) {
|
|
231
|
+
if (this.translatorMap[clusterDetails.authProvider]) {
|
|
232
|
+
return this.translatorMap[clusterDetails.authProvider].decorateClusterDetailsWithAuth(clusterDetails, auth);
|
|
233
|
+
}
|
|
234
|
+
throw new Error(
|
|
235
|
+
`authProvider "${clusterDetails.authProvider}" has no KubernetesAuthTranslator associated with it`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
226
240
|
class NoopKubernetesAuthTranslator {
|
|
227
241
|
async decorateClusterDetailsWithAuth(clusterDetails) {
|
|
228
242
|
return clusterDetails;
|
|
@@ -254,39 +268,6 @@ class OidcKubernetesAuthTranslator {
|
|
|
254
268
|
}
|
|
255
269
|
}
|
|
256
270
|
|
|
257
|
-
class KubernetesAuthTranslatorGenerator {
|
|
258
|
-
static getKubernetesAuthTranslatorInstance(authProvider, options) {
|
|
259
|
-
switch (authProvider) {
|
|
260
|
-
case "google": {
|
|
261
|
-
return new GoogleKubernetesAuthTranslator();
|
|
262
|
-
}
|
|
263
|
-
case "aws": {
|
|
264
|
-
return new AwsIamKubernetesAuthTranslator();
|
|
265
|
-
}
|
|
266
|
-
case "azure": {
|
|
267
|
-
return new AzureIdentityKubernetesAuthTranslator(options.logger);
|
|
268
|
-
}
|
|
269
|
-
case "serviceAccount": {
|
|
270
|
-
return new NoopKubernetesAuthTranslator();
|
|
271
|
-
}
|
|
272
|
-
case "googleServiceAccount": {
|
|
273
|
-
return new GoogleServiceAccountAuthTranslator();
|
|
274
|
-
}
|
|
275
|
-
case "oidc": {
|
|
276
|
-
return new OidcKubernetesAuthTranslator();
|
|
277
|
-
}
|
|
278
|
-
case "localKubectlProxy": {
|
|
279
|
-
return new NoopKubernetesAuthTranslator();
|
|
280
|
-
}
|
|
281
|
-
default: {
|
|
282
|
-
throw new Error(
|
|
283
|
-
`authProvider "${authProvider}" has no KubernetesAuthTranslator associated with it`
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
271
|
class ConfigClusterLocator {
|
|
291
272
|
constructor(clusterDetails) {
|
|
292
273
|
this.clusterDetails = clusterDetails;
|
|
@@ -742,14 +723,15 @@ class KubernetesFanOutHandler {
|
|
|
742
723
|
fetcher,
|
|
743
724
|
serviceLocator,
|
|
744
725
|
customResources,
|
|
745
|
-
objectTypesToFetch = DEFAULT_OBJECTS
|
|
726
|
+
objectTypesToFetch = DEFAULT_OBJECTS,
|
|
727
|
+
authTranslator
|
|
746
728
|
}) {
|
|
747
729
|
this.logger = logger;
|
|
748
730
|
this.fetcher = fetcher;
|
|
749
731
|
this.serviceLocator = serviceLocator;
|
|
750
732
|
this.customResources = customResources;
|
|
751
733
|
this.objectTypesToFetch = new Set(objectTypesToFetch);
|
|
752
|
-
this.
|
|
734
|
+
this.authTranslator = authTranslator;
|
|
753
735
|
}
|
|
754
736
|
async getCustomResourcesByEntity({
|
|
755
737
|
entity,
|
|
@@ -811,11 +793,7 @@ class KubernetesFanOutHandler {
|
|
|
811
793
|
const clusterDetails = (await this.serviceLocator.getClustersByEntity(entity, requestContext)).clusters;
|
|
812
794
|
const promiseResults = await Promise.allSettled(
|
|
813
795
|
clusterDetails.map((cd) => {
|
|
814
|
-
|
|
815
|
-
return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(
|
|
816
|
-
cd,
|
|
817
|
-
auth
|
|
818
|
-
);
|
|
796
|
+
return this.authTranslator.decorateClusterDetailsWithAuth(cd, auth);
|
|
819
797
|
})
|
|
820
798
|
);
|
|
821
799
|
promiseResults.filter(isRejected).map((item) => {
|
|
@@ -873,18 +851,6 @@ class KubernetesFanOutHandler {
|
|
|
873
851
|
result.errors.push(...podMetrics.errors);
|
|
874
852
|
return [result, podMetrics.responses];
|
|
875
853
|
}
|
|
876
|
-
getAuthTranslator(provider) {
|
|
877
|
-
if (this.authTranslators[provider]) {
|
|
878
|
-
return this.authTranslators[provider];
|
|
879
|
-
}
|
|
880
|
-
this.authTranslators[provider] = KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(
|
|
881
|
-
provider,
|
|
882
|
-
{
|
|
883
|
-
logger: this.logger
|
|
884
|
-
}
|
|
885
|
-
);
|
|
886
|
-
return this.authTranslators[provider];
|
|
887
|
-
}
|
|
888
854
|
}
|
|
889
855
|
|
|
890
856
|
const isError = (fr) => fr.hasOwnProperty("errorType");
|
|
@@ -989,7 +955,7 @@ class KubernetesClientBasedFetcher {
|
|
|
989
955
|
resourcePath += `/${encode(plural)}`;
|
|
990
956
|
let url;
|
|
991
957
|
let requestInit;
|
|
992
|
-
if (clusterDetails.serviceAccountToken) {
|
|
958
|
+
if (clusterDetails.serviceAccountToken || clusterDetails.authProvider === "localKubectlProxy") {
|
|
993
959
|
[url, requestInit] = this.fetchArgsFromClusterDetails(clusterDetails);
|
|
994
960
|
} else if (fs__default["default"].pathExistsSync(clientNode.Config.SERVICEACCOUNT_TOKEN_PATH)) {
|
|
995
961
|
[url, requestInit] = this.fetchArgsInCluster();
|
|
@@ -1059,10 +1025,11 @@ class KubernetesClientBasedFetcher {
|
|
|
1059
1025
|
const HEADER_KUBERNETES_CLUSTER = "Backstage-Kubernetes-Cluster";
|
|
1060
1026
|
const HEADER_KUBERNETES_AUTH = "Backstage-Kubernetes-Authorization";
|
|
1061
1027
|
class KubernetesProxy {
|
|
1062
|
-
constructor(
|
|
1063
|
-
this.logger = logger;
|
|
1064
|
-
this.clusterSupplier = clusterSupplier;
|
|
1028
|
+
constructor(options) {
|
|
1065
1029
|
this.middlewareForClusterName = /* @__PURE__ */ new Map();
|
|
1030
|
+
this.logger = options.logger;
|
|
1031
|
+
this.clusterSupplier = options.clusterSupplier;
|
|
1032
|
+
this.authTranslator = options.authTranslator;
|
|
1066
1033
|
}
|
|
1067
1034
|
createRequestHandler(options) {
|
|
1068
1035
|
const { permissionApi } = options;
|
|
@@ -1080,6 +1047,12 @@ class KubernetesProxy {
|
|
|
1080
1047
|
res.status(403).json({ error: new errors.NotAllowedError("Unauthorized") });
|
|
1081
1048
|
return;
|
|
1082
1049
|
}
|
|
1050
|
+
const cluster = await this.getClusterForRequest(req).then(
|
|
1051
|
+
(cd) => this.authTranslator.decorateClusterDetailsWithAuth(cd, {})
|
|
1052
|
+
);
|
|
1053
|
+
if (!req.headers.authorization) {
|
|
1054
|
+
req.headers.authorization = `Bearer ${cluster.serviceAccountToken}`;
|
|
1055
|
+
}
|
|
1083
1056
|
const middleware = await this.getMiddleware(req);
|
|
1084
1057
|
middleware(req, res, next);
|
|
1085
1058
|
};
|
|
@@ -1124,8 +1097,10 @@ class KubernetesProxy {
|
|
|
1124
1097
|
},
|
|
1125
1098
|
onProxyReq: (proxyReq, req) => {
|
|
1126
1099
|
var _a;
|
|
1127
|
-
|
|
1128
|
-
|
|
1100
|
+
if (req.header(HEADER_KUBERNETES_AUTH)) {
|
|
1101
|
+
const token = (_a = req.header(HEADER_KUBERNETES_AUTH)) != null ? _a : "";
|
|
1102
|
+
proxyReq.setHeader("Authorization", token);
|
|
1103
|
+
}
|
|
1129
1104
|
}
|
|
1130
1105
|
});
|
|
1131
1106
|
this.middlewareForClusterName.set(originalCluster.name, middleware);
|
|
@@ -1174,6 +1149,7 @@ class KubernetesBuilder {
|
|
|
1174
1149
|
const customResources = this.buildCustomResources();
|
|
1175
1150
|
const fetcher = this.getFetcher();
|
|
1176
1151
|
const clusterSupplier = this.getClusterSupplier();
|
|
1152
|
+
const authTranslatorMap = this.getAuthTranslatorMap();
|
|
1177
1153
|
const proxy = this.getProxy(logger, clusterSupplier);
|
|
1178
1154
|
const serviceLocator = this.getServiceLocator();
|
|
1179
1155
|
const objectsProvider = this.getObjectsProvider({
|
|
@@ -1197,7 +1173,8 @@ class KubernetesBuilder {
|
|
|
1197
1173
|
proxy,
|
|
1198
1174
|
objectsProvider,
|
|
1199
1175
|
router,
|
|
1200
|
-
serviceLocator
|
|
1176
|
+
serviceLocator,
|
|
1177
|
+
authTranslatorMap
|
|
1201
1178
|
};
|
|
1202
1179
|
}
|
|
1203
1180
|
setClusterSupplier(clusterSupplier) {
|
|
@@ -1224,6 +1201,9 @@ class KubernetesBuilder {
|
|
|
1224
1201
|
this.proxy = proxy;
|
|
1225
1202
|
return this;
|
|
1226
1203
|
}
|
|
1204
|
+
setAuthTranslatorMap(authTranslatorMap) {
|
|
1205
|
+
this.authTranslatorMap = authTranslatorMap;
|
|
1206
|
+
}
|
|
1227
1207
|
buildCustomResources() {
|
|
1228
1208
|
var _a;
|
|
1229
1209
|
const customResources = ((_a = this.env.config.getOptionalConfigArray("kubernetes.customResources")) != null ? _a : []).map(
|
|
@@ -1249,7 +1229,13 @@ class KubernetesBuilder {
|
|
|
1249
1229
|
return this.clusterSupplier;
|
|
1250
1230
|
}
|
|
1251
1231
|
buildObjectsProvider(options) {
|
|
1252
|
-
|
|
1232
|
+
const authTranslatorMap = this.getAuthTranslatorMap();
|
|
1233
|
+
this.objectsProvider = new KubernetesFanOutHandler({
|
|
1234
|
+
...options,
|
|
1235
|
+
authTranslator: new DispatchingKubernetesAuthTranslator({
|
|
1236
|
+
authTranslatorMap
|
|
1237
|
+
})
|
|
1238
|
+
});
|
|
1253
1239
|
return this.objectsProvider;
|
|
1254
1240
|
}
|
|
1255
1241
|
buildFetcher() {
|
|
@@ -1280,7 +1266,15 @@ class KubernetesBuilder {
|
|
|
1280
1266
|
throw new Error("not implemented");
|
|
1281
1267
|
}
|
|
1282
1268
|
buildProxy(logger, clusterSupplier) {
|
|
1283
|
-
|
|
1269
|
+
const authTranslatorMap = this.getAuthTranslatorMap();
|
|
1270
|
+
const authTranslator = new DispatchingKubernetesAuthTranslator({
|
|
1271
|
+
authTranslatorMap
|
|
1272
|
+
});
|
|
1273
|
+
this.proxy = new KubernetesProxy({
|
|
1274
|
+
logger,
|
|
1275
|
+
clusterSupplier,
|
|
1276
|
+
authTranslator
|
|
1277
|
+
});
|
|
1284
1278
|
return this.proxy;
|
|
1285
1279
|
}
|
|
1286
1280
|
buildRouter(objectsProvider, clusterSupplier, catalogApi, proxy, permissionApi) {
|
|
@@ -1323,6 +1317,18 @@ class KubernetesBuilder {
|
|
|
1323
1317
|
addResourceRoutesToRouter(router, catalogApi, objectsProvider);
|
|
1324
1318
|
return router;
|
|
1325
1319
|
}
|
|
1320
|
+
buildAuthTranslatorMap() {
|
|
1321
|
+
this.authTranslatorMap = {
|
|
1322
|
+
google: new GoogleKubernetesAuthTranslator(),
|
|
1323
|
+
aws: new AwsIamKubernetesAuthTranslator(),
|
|
1324
|
+
azure: new AzureIdentityKubernetesAuthTranslator(this.env.logger),
|
|
1325
|
+
serviceAccount: new NoopKubernetesAuthTranslator(),
|
|
1326
|
+
googleServiceAccount: new GoogleServiceAccountAuthTranslator(),
|
|
1327
|
+
oidc: new OidcKubernetesAuthTranslator(),
|
|
1328
|
+
localKubectlProxy: new NoopKubernetesAuthTranslator()
|
|
1329
|
+
};
|
|
1330
|
+
return this.authTranslatorMap;
|
|
1331
|
+
}
|
|
1326
1332
|
async fetchClusterDetails(clusterSupplier) {
|
|
1327
1333
|
const clusterDetails = await clusterSupplier.getClusters();
|
|
1328
1334
|
this.env.logger.info(
|
|
@@ -1381,6 +1387,10 @@ class KubernetesBuilder {
|
|
|
1381
1387
|
var _a;
|
|
1382
1388
|
return (_a = this.proxy) != null ? _a : this.buildProxy(logger, clusterSupplier);
|
|
1383
1389
|
}
|
|
1390
|
+
getAuthTranslatorMap() {
|
|
1391
|
+
var _a;
|
|
1392
|
+
return (_a = this.authTranslatorMap) != null ? _a : this.buildAuthTranslatorMap();
|
|
1393
|
+
}
|
|
1384
1394
|
}
|
|
1385
1395
|
|
|
1386
1396
|
async function createRouter(options) {
|
|
@@ -1391,11 +1401,11 @@ async function createRouter(options) {
|
|
|
1391
1401
|
exports.AwsIamKubernetesAuthTranslator = AwsIamKubernetesAuthTranslator;
|
|
1392
1402
|
exports.AzureIdentityKubernetesAuthTranslator = AzureIdentityKubernetesAuthTranslator;
|
|
1393
1403
|
exports.DEFAULT_OBJECTS = DEFAULT_OBJECTS;
|
|
1404
|
+
exports.DispatchingKubernetesAuthTranslator = DispatchingKubernetesAuthTranslator;
|
|
1394
1405
|
exports.GoogleKubernetesAuthTranslator = GoogleKubernetesAuthTranslator;
|
|
1395
1406
|
exports.GoogleServiceAccountAuthTranslator = GoogleServiceAccountAuthTranslator;
|
|
1396
1407
|
exports.HEADER_KUBERNETES_AUTH = HEADER_KUBERNETES_AUTH;
|
|
1397
1408
|
exports.HEADER_KUBERNETES_CLUSTER = HEADER_KUBERNETES_CLUSTER;
|
|
1398
|
-
exports.KubernetesAuthTranslatorGenerator = KubernetesAuthTranslatorGenerator;
|
|
1399
1409
|
exports.KubernetesBuilder = KubernetesBuilder;
|
|
1400
1410
|
exports.KubernetesProxy = KubernetesProxy;
|
|
1401
1411
|
exports.NoopKubernetesAuthTranslator = NoopKubernetesAuthTranslator;
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/CatalogClusterLocator.ts","../src/cluster-locator/LocalKubectlProxyLocator.ts","../src/cluster-locator/index.ts","../src/routes/resourcesRoutes.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesProxy.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\n/**\n *\n * @public\n */\nexport type SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\n/**\n *\n * @public\n */\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n const awsCreds = await this.awsGetCredentials();\n\n if (!(awsCreds instanceof Credentials))\n throw new Error('No AWS credentials found.');\n\n let creds: SigningCreds = {\n accessKeyId: awsCreds.accessKeyId,\n secretAccessKey: awsCreds.secretAccessKey,\n sessionToken: awsCreds.sessionToken,\n };\n\n if (!this.validCredentials(creds))\n throw new Error('Invalid AWS credentials found.');\n if (!assumeRole) return creds;\n\n try {\n const params: AWS.STS.Types.AssumeRoleRequest = {\n RoleArn: assumeRole,\n RoleSessionName: 'backstage-login',\n };\n if (externalId) params.ExternalId = externalId;\n\n const assumedRole = await new AWS.STS().assumeRole(params).promise();\n\n if (!assumedRole.Credentials) {\n throw new Error(`No credentials returned for role ${assumeRole}`);\n }\n\n creds = {\n accessKeyId: assumedRole.Credentials.AccessKeyId,\n secretAccessKey: assumedRole.Credentials.SecretAccessKey,\n sessionToken: assumedRole.Credentials.SessionToken,\n };\n } catch (e) {\n console.warn(`There was an error assuming the role: ${e}`);\n throw new Error(`Unable to assume role: ${e}`);\n }\n return creds;\n }\n async getBearerToken(\n clusterName: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const credentials = await this.getCredentials(assumeRole, externalId);\n\n const request = {\n host: `sts.amazonaws.com`,\n path: `/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Expires=60`,\n headers: {\n 'x-k8s-aws-id': clusterName,\n },\n signQuery: true,\n };\n\n const signed = sign(request, credentials);\n const url = `https://${signed.host}${signed.path}`;\n const base64Url = Buffer.from(url, 'binary').toString('base64');\n const urlSafeBase64Url = base64Url\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return `k8s-aws-v1.${urlSafeBase64Url}`;\n }\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AWSClusterDetails,\n ): Promise<AWSClusterDetails> {\n const clusterDetailsWithAuthToken: AWSClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getBearerToken(\n clusterDetails.name,\n clusterDetails.assumeRole,\n clusterDetails.externalId,\n );\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\n/**\n *\n * @public\n */\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = authConfig.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\n/**\n *\n * @public\n */\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\n\n/**\n *\n * @public\n */\nexport class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined = authConfig.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { NoopKubernetesAuthTranslator } from './NoopKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\n/**\n *\n * @public\n */\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n options: {\n logger: Logger;\n },\n ): KubernetesAuthTranslator {\n switch (authProvider) {\n case 'google': {\n return new GoogleKubernetesAuthTranslator();\n }\n case 'aws': {\n return new AwsIamKubernetesAuthTranslator();\n }\n case 'azure': {\n return new AzureIdentityKubernetesAuthTranslator(options.logger);\n }\n case 'serviceAccount': {\n return new NoopKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n case 'localKubectlProxy': {\n return new NoopKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\n }\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n caFile: c.getOptionalString('caFile'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\n );\n }\n }\n}\n","/*\n * Copyright 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 */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { CATALOG_FILTER_EXISTS, CatalogApi } from '@backstage/catalog-client';\nimport {\n ANNOTATION_KUBERNETES_API_SERVER,\n ANNOTATION_KUBERNETES_API_SERVER_CA,\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP,\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY,\n ANNOTATION_KUBERNETES_DASHBOARD_URL,\n ANNOTATION_KUBERNETES_DASHBOARD_APP,\n} from '@backstage/plugin-kubernetes-common';\n\nexport class CatalogClusterLocator implements KubernetesClustersSupplier {\n private catalogClient: CatalogApi;\n\n constructor(catalogClient: CatalogApi) {\n this.catalogClient = catalogClient;\n }\n\n static fromConfig(catalogApi: CatalogApi): CatalogClusterLocator {\n return new CatalogClusterLocator(catalogApi);\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n const apiServerKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER}`;\n const apiServerCaKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER_CA}`;\n const authProviderKey = `metadata.annotations.${ANNOTATION_KUBERNETES_AUTH_PROVIDER}`;\n\n const filter: Record<string, symbol | string> = {\n kind: 'Resource',\n 'spec.type': 'kubernetes-cluster',\n [apiServerKey]: CATALOG_FILTER_EXISTS,\n [apiServerCaKey]: CATALOG_FILTER_EXISTS,\n [authProviderKey]: CATALOG_FILTER_EXISTS,\n };\n\n const clusters = await this.catalogClient.getEntities({\n filter: [filter],\n });\n return clusters.items.map(entity => {\n const clusterDetails: ClusterDetails = {\n name: entity.metadata.name,\n url: entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER]!,\n caData:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER_CA]!,\n authProvider:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_AUTH_PROVIDER]!,\n oidcTokenProvider:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER\n ]!,\n skipMetricsLookup:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP\n ]! === 'true'\n ? true\n : false,\n skipTLSVerify:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY\n ]! === 'true'\n ? true\n : false,\n dashboardUrl:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_URL]!,\n dashboardApp:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_APP]!,\n };\n\n return clusterDetails;\n });\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class LocalKubectlProxyClusterLocator\n implements KubernetesClustersSupplier\n{\n private readonly clusterDetails: ClusterDetails[];\n\n public constructor() {\n this.clusterDetails = [\n {\n name: 'local',\n url: 'http:/localhost:8001',\n authProvider: 'localKubectlProxy',\n skipMetricsLookup: true,\n },\n ];\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\nimport { CatalogClusterLocator } from './CatalogClusterLocator';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { LocalKubectlProxyClusterLocator } from './LocalKubectlProxyLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n catalogClient: CatalogApi,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'catalog':\n return CatalogClusterLocator.fromConfig(catalogClient);\n case 'localKubectlProxy':\n return new LocalKubectlProxyClusterLocator();\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\n};\n","/*\n * Copyright 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, AuthenticationError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '../types/types';\nimport { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalogApi: CatalogApi,\n objectsProvider: KubernetesObjectsProvider,\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 = getBearerTokenFromAuthorizationHeader(\n req.headers.authorization,\n );\n\n if (!token) {\n throw new AuthenticationError('No Backstage token');\n }\n\n const entity = await catalogApi.getEntityByRef(entityRef, {\n token: token,\n });\n\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity,\n auth: req.body.auth,\n });\n res.json(response);\n });\n\n router.post('/resources/custom/query', async (req, res) => {\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 entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n });\n res.json(response);\n });\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n ServiceLocatorRequestContext,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n getClustersByEntity(\n _entity: Entity,\n _requestContext: ServiceLocatorRequestContext,\n ): Promise<{ clusters: ClusterDetails[] }> {\n return this.clusterSupplier.getClusters().then(clusters => ({ clusters }));\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n CustomResource,\n CustomResourcesByEntity,\n KubernetesObjectsByEntity,\n ServiceLocatorRequestContext,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n KubernetesRequestAuth,\n CustomResourceMatcher,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\nconst isRejected = (\n input: PromiseSettledResult<unknown>,\n): input is PromiseRejectedResult => input.status === 'rejected';\n\nconst isFulfilled = <T>(\n input: PromiseSettledResult<T>,\n): input is PromiseFulfilledResult<T> => input.status === 'fulfilled';\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: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'daemonsets',\n objectType: 'daemonsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: 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 {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslators: Record<string, KubernetesAuthTranslator>;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n }: KubernetesFanOutHandlerOptions) {\n this.logger = logger;\n this.fetcher = fetcher;\n this.serviceLocator = serviceLocator;\n this.customResources = customResources;\n this.objectTypesToFetch = new Set(objectTypesToFetch);\n this.authTranslators = {};\n }\n\n async getCustomResourcesByEntity({\n entity,\n auth,\n customResources,\n }: CustomResourcesByEntity): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity({\n entity,\n auth,\n }: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(entity, auth, this.objectTypesToFetch);\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n objectTypesToFetch: Set<ObjectToFetch>,\n customResources?: CustomResourceMatcher[],\n ) {\n const entityName =\n entity.metadata?.annotations?.['backstage.io/kubernetes-id'] ||\n entity.metadata?.name;\n\n const clusterDetailsDecoratedForAuth: ClusterDetails[] =\n await this.decorateClusterDetailsWithAuth(entity, auth, {\n objectTypesToFetch: objectTypesToFetch,\n customResources: customResources ?? [],\n });\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: objectTypesToFetch,\n labelSelector,\n customResources: (\n customResources ||\n clusterDetailsItem.customResources ||\n this.customResources\n ).map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\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(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n private async decorateClusterDetailsWithAuth(\n entity: Entity,\n auth: KubernetesRequestAuth,\n requestContext: ServiceLocatorRequestContext,\n ) {\n const clusterDetails: ClusterDetails[] = (\n await this.serviceLocator.getClustersByEntity(entity, requestContext)\n ).clusters;\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n const promiseResults = await Promise.allSettled(\n clusterDetails.map(cd => {\n const kubernetesAuthTranslator: KubernetesAuthTranslator =\n this.getAuthTranslator(cd.authProvider);\n return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(\n cd,\n auth,\n );\n }),\n );\n\n promiseResults.filter(isRejected).map(item => {\n this.logger.info(`Failed to decorate cluster details: ${item.reason}`);\n });\n return promiseResults.filter(isFulfilled).map(item => item.value);\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources?.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n if (namespaces.size === 0) {\n return [result, []];\n }\n\n const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces(\n clusterDetails,\n namespaces,\n );\n\n result.errors.push(...podMetrics.errors);\n return [result, podMetrics.responses as PodStatusFetchResponse[]];\n }\n\n private getAuthTranslator(provider: string): KubernetesAuthTranslator {\n if (this.authTranslators[provider]) {\n return this.authTranslators[provider];\n }\n\n this.authTranslators[provider] =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n provider,\n {\n logger: this.logger,\n },\n );\n return this.authTranslators[provider];\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Config,\n Cluster,\n CoreV1Api,\n KubeConfig,\n Metrics,\n User,\n bufferFromFileOrString,\n topPods,\n} from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n ObjectFetchParams,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\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';\n\nexport interface KubernetesClientBasedFetcherOptions {\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 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: Logger;\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 group,\n apiVersion,\n plural,\n params.namespace,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n ).then(\n (r: Response): Promise<FetchResult> =>\n r.ok\n ? r.json().then(\n ({ items }): FetchResponse => ({\n type: objectType,\n resources: items,\n }),\n )\n : this.handleUnsuccessfulResponse(params.clusterDetails.name, r),\n ),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespaces(\n clusterDetails: ClusterDetails,\n namespaces: Set<string>,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(namespaces).map(async ns => {\n const [podMetrics, podList] = await Promise.all([\n this.fetchResource(\n clusterDetails,\n 'metrics.k8s.io',\n 'v1beta1',\n 'pods',\n ns,\n ),\n this.fetchResource(clusterDetails, '', 'v1', 'pods', ns),\n ]);\n if (podMetrics.ok && podList.ok) {\n return topPods(\n {\n listPodForAllNamespaces: () =>\n podList.json().then(b => ({ body: b })),\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 fetchResource(\n clusterDetails: ClusterDetails,\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 if (clusterDetails.serviceAccountToken) {\n [url, requestInit] = this.fetchArgsFromClusterDetails(clusterDetails);\n } else if (fs.pathExistsSync(Config.SERVICEACCOUNT_TOKEN_PATH)) {\n [url, requestInit] = this.fetchArgsInCluster();\n } else {\n return Promise.reject(\n new Error(\n `no bearer token 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=${labelSelector}`;\n }\n\n return fetch(url, requestInit);\n }\n\n private fetchArgsFromClusterDetails(\n clusterDetails: ClusterDetails,\n ): [URL, RequestInit] {\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${clusterDetails.serviceAccountToken}`,\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 });\n }\n return [url, requestInit];\n }\n private fetchArgsInCluster(): [URL, RequestInit] {\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 const user = kc.getCurrentUser() as User;\n\n const token = fs.readFileSync(user.authProvider.config.tokenFile);\n\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n };\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","/*\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 */\n\nimport {\n ErrorResponseBody,\n ForwardedError,\n InputError,\n NotAllowedError,\n NotFoundError,\n serializeError,\n} from '@backstage/errors';\nimport { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';\nimport { kubernetesProxyPermission } from '@backstage/plugin-kubernetes-common';\nimport {\n PermissionEvaluator,\n AuthorizeResult,\n} from '@backstage/plugin-permission-common';\nimport { bufferFromFileOrString } from '@kubernetes/client-node';\nimport type { Request, RequestHandler } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\nimport { Logger } from 'winston';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport const APPLICATION_JSON: string = 'application/json';\n\n/**\n * The header that is used to specify the cluster name.\n *\n * @public\n */\nexport const HEADER_KUBERNETES_CLUSTER: string = 'Backstage-Kubernetes-Cluster';\n\n/**\n * The header that is used to specify the Authentication Authorities token.\n * e.x if using the google auth provider as your authentication authority then this field would be the google provided bearer token.\n * @public\n */\nexport const HEADER_KUBERNETES_AUTH: string =\n 'Backstage-Kubernetes-Authorization';\n\n/**\n * The options object expected to be passed as a parameter to KubernetesProxy.createRequestHandler().\n *\n * @public\n */\nexport type KubernetesProxyCreateRequestHandlerOptions = {\n permissionApi: PermissionEvaluator;\n};\n\n/**\n * A proxy that routes requests to the Kubernetes API.\n *\n * @public\n */\nexport class KubernetesProxy {\n private readonly middlewareForClusterName = new Map<string, RequestHandler>();\n\n constructor(\n private readonly logger: Logger,\n private readonly clusterSupplier: KubernetesClustersSupplier,\n ) {}\n\n public createRequestHandler(\n options: KubernetesProxyCreateRequestHandlerOptions,\n ): RequestHandler {\n const { permissionApi } = options;\n return async (req, res, next) => {\n const token = getBearerTokenFromAuthorizationHeader(\n req.header('authorization'),\n );\n\n const authorizeResponse = (\n await permissionApi.authorize(\n [{ permission: kubernetesProxyPermission }],\n {\n token,\n },\n )\n )[0];\n\n if (authorizeResponse.result === AuthorizeResult.DENY) {\n res.status(403).json({ error: new NotAllowedError('Unauthorized') });\n return;\n }\n\n const middleware = await this.getMiddleware(req);\n middleware(req, res, next);\n };\n }\n\n // We create one middleware per remote cluster and hold on to them, because\n // the secure property isn't possible to decide on a per-request basis with a\n // single middleware instance - and we don't expect it to change over time.\n private async getMiddleware(originalReq: Request): Promise<RequestHandler> {\n const originalCluster = await this.getClusterForRequest(originalReq);\n let middleware = this.middlewareForClusterName.get(originalCluster.name);\n if (!middleware) {\n // Probably too risky without permissions protecting this endpoint\n // if (cluster.serviceAccountToken) {\n // options.headers = {\n // Authorization: `Bearer ${cluster.serviceAccountToken}`,\n // };\n // }\n\n const logger = this.logger.child({ cluster: originalCluster.name });\n middleware = createProxyMiddleware({\n logProvider: () => logger,\n secure: !originalCluster.skipTLSVerify,\n router: async req => {\n // Re-evaluate the cluster on each request, in case it has changed\n const cluster = await this.getClusterForRequest(req);\n const url = new URL(cluster.url);\n return {\n protocol: url.protocol,\n host: url.hostname,\n port: url.port,\n ca: bufferFromFileOrString('', cluster.caData)?.toString(),\n };\n },\n pathRewrite: { [`^${originalReq.baseUrl}`]: '' },\n onError: (error, req, res) => {\n const wrappedError = new ForwardedError(\n `Cluster '${originalCluster.name}' request error`,\n error,\n );\n\n logger.error(wrappedError);\n\n const body: ErrorResponseBody = {\n error: serializeError(wrappedError, {\n includeStack: process.env.NODE_ENV === 'development',\n }),\n request: { method: req.method, url: req.originalUrl },\n response: { statusCode: 500 },\n };\n\n res.status(500).json(body);\n },\n onProxyReq: (proxyReq, req) => {\n // the kubernetes proxy endpoint expects a header field labeled `Backstage-Kubernetes-Authorization` that will be used to authenticate with the Kubernetes Api. The token provided as a value should be an bearer token for the target cluster.\n const token = req.header(HEADER_KUBERNETES_AUTH) ?? '';\n proxyReq.setHeader('Authorization', token);\n },\n });\n\n this.middlewareForClusterName.set(originalCluster.name, middleware);\n }\n\n return middleware;\n }\n\n private async getClusterForRequest(req: Request): Promise<ClusterDetails> {\n const clusterName = req.header(HEADER_KUBERNETES_CLUSTER);\n if (!clusterName) {\n throw new InputError(`Missing '${HEADER_KUBERNETES_CLUSTER}' header.`);\n }\n\n const cluster = await this.clusterSupplier\n .getClusters()\n .then(clusters => clusters.find(c => c.name === clusterName));\n if (!cluster) {\n throw new NotFoundError(`Cluster '${clusterName}' not found`);\n }\n\n return cluster;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { Config } from '@backstage/config';\nimport { kubernetesPermissions } from '@backstage/plugin-kubernetes-common';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Duration } from 'luxon';\nimport { Logger } from 'winston';\n\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { addResourceRoutesToRouter } from '../routes/resourcesRoutes';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n CustomResource,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesObjectsProvider,\n KubernetesObjectsProviderOptions,\n KubernetesObjectTypes,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n ServiceLocatorMethod,\n} from '../types/types';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\nimport { KubernetesProxy } from './KubernetesProxy';\n\n/**\n *\n * @public\n */\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n permissions: PermissionEvaluator;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @public\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n proxy: KubernetesProxy;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\n/**\n *\n * @public\n */\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n private proxy?: KubernetesProxy;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n const permissions = this.env.permissions;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.getFetcher();\n\n const clusterSupplier = this.getClusterSupplier();\n\n const proxy = this.getProxy(logger, clusterSupplier);\n\n const serviceLocator = this.getServiceLocator();\n\n const objectsProvider = this.getObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(\n objectsProvider,\n clusterSupplier,\n this.env.catalogApi,\n proxy,\n permissions,\n );\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n proxy,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n public setProxy(proxy?: KubernetesProxy) {\n this.proxy = proxy;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n this.clusterSupplier = getCombinedClusterSupplier(\n config,\n this.env.catalogApi,\n refreshInterval,\n );\n\n return this.clusterSupplier;\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n this.objectsProvider = new KubernetesFanOutHandler(options);\n return this.objectsProvider;\n }\n\n protected buildFetcher(): KubernetesFetcher {\n this.fetcher = new KubernetesClientBasedFetcher({\n logger: this.env.logger,\n });\n\n return this.fetcher;\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n this.serviceLocator =\n this.buildMultiTenantServiceLocator(clusterSupplier);\n break;\n case 'http':\n this.serviceLocator = this.buildHttpServiceLocator(clusterSupplier);\n break;\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n\n return this.serviceLocator;\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesProxy {\n this.proxy = new KubernetesProxy(logger, clusterSupplier);\n return this.proxy;\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n catalogApi: CatalogApi,\n proxy: KubernetesProxy,\n permissionApi: PermissionEvaluator,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use('/proxy', proxy.createRequestHandler({ permissionApi }));\n router.use(express.json());\n router.use(\n createPermissionIntegrationRouter({\n permissions: kubernetesPermissions,\n }),\n );\n // @deprecated\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity: requestBody.entity,\n auth: requestBody.auth || {},\n });\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n\n addResourceRoutesToRouter(router, catalogApi, objectsProvider);\n\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getFetcher(): KubernetesFetcher {\n return this.fetcher ?? this.buildFetcher();\n }\n\n protected getClusterSupplier() {\n return (\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval)\n );\n }\n\n protected getServiceLocator(): KubernetesServiceLocator {\n return (\n this.serviceLocator ??\n this.buildServiceLocator(\n this.getServiceLocatorMethod(),\n this.getClusterSupplier(),\n )\n );\n }\n\n protected getObjectsProvider(options: KubernetesObjectsProviderOptions) {\n return this.objectsProvider ?? this.buildObjectsProvider(options);\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\n }\n\n protected getProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n return this.proxy ?? this.buildProxy(logger, clusterSupplier);\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\nimport { PluginEndpointDiscovery } from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\n\n/**\n *\n * @public\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n clusterSupplier?: KubernetesClustersSupplier;\n discovery: PluginEndpointDiscovery;\n permissions: PermissionEvaluator;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["AWS","Credentials","sign","DefaultAzureCredential","container","_a","ForwardedError","ANNOTATION_KUBERNETES_API_SERVER","ANNOTATION_KUBERNETES_API_SERVER_CA","ANNOTATION_KUBERNETES_AUTH_PROVIDER","CATALOG_FILTER_EXISTS","ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER","ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP","ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY","ANNOTATION_KUBERNETES_DASHBOARD_URL","ANNOTATION_KUBERNETES_DASHBOARD_APP","InputError","parseEntityRef","getBearerTokenFromAuthorizationHeader","AuthenticationError","stringifyEntityRef","lodash","topPods","fs","Config","fetch","https","bufferFromFileOrString","KubeConfig","kubernetesProxyPermission","AuthorizeResult","NotAllowedError","createProxyMiddleware","serializeError","NotFoundError","Duration","Router","express","createPermissionIntegrationRouter","kubernetesPermissions"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCO,MAAM,8BAEb,CAAA;AAAA,EAFO,WAAA,GAAA;AAOL,IAAA,IAAA,CAAA,iBAAA,GAAoB,YAAkC;AACpD,MAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAW,KAAA;AACtC,QAAIA,uBAAA,CAAA,MAAA,CAAO,eAAe,CAAO,GAAA,KAAA;AAC/B,UAAA,IAAI,GAAK,EAAA;AACP,YAAA,OAAO,OAAO,GAAG,CAAA,CAAA;AAAA,WACnB;AAEA,UAAO,OAAA,OAAA,CAAQA,uBAAI,CAAA,MAAA,CAAO,WAA0B,CAAA,CAAA;AAAA,SACrD,CAAA,CAAA;AAAA,OACF,CAAA,CAAA;AAAA,KACH,CAAA;AAAA,GAAA;AAAA,EAdA,iBAAiB,KAA8B,EAAA;AAC7C,IAAQ,OAAA,CAAA,KAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,KAAA,CAAO,iBAAe,KAAO,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,KAAA,CAAA,eAAA,CAAA,CAAA;AAAA,GACvC;AAAA,EAcA,MAAM,cACJ,CAAA,UAAA,EACA,UACuB,EAAA;AACvB,IAAM,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,iBAAkB,EAAA,CAAA;AAE9C,IAAA,IAAI,EAAE,QAAoB,YAAAC,eAAA,CAAA;AACxB,MAAM,MAAA,IAAI,MAAM,2BAA2B,CAAA,CAAA;AAE7C,IAAA,IAAI,KAAsB,GAAA;AAAA,MACxB,aAAa,QAAS,CAAA,WAAA;AAAA,MACtB,iBAAiB,QAAS,CAAA,eAAA;AAAA,MAC1B,cAAc,QAAS,CAAA,YAAA;AAAA,KACzB,CAAA;AAEA,IAAI,IAAA,CAAC,IAAK,CAAA,gBAAA,CAAiB,KAAK,CAAA;AAC9B,MAAM,MAAA,IAAI,MAAM,gCAAgC,CAAA,CAAA;AAClD,IAAA,IAAI,CAAC,UAAA;AAAY,MAAO,OAAA,KAAA,CAAA;AAExB,IAAI,IAAA;AACF,MAAA,MAAM,MAA0C,GAAA;AAAA,QAC9C,OAAS,EAAA,UAAA;AAAA,QACT,eAAiB,EAAA,iBAAA;AAAA,OACnB,CAAA;AACA,MAAI,IAAA,UAAA;AAAY,QAAA,MAAA,CAAO,UAAa,GAAA,UAAA,CAAA;AAEpC,MAAM,MAAA,WAAA,GAAc,MAAM,IAAID,uBAAA,CAAI,KAAM,CAAA,UAAA,CAAW,MAAM,CAAA,CAAE,OAAQ,EAAA,CAAA;AAEnE,MAAI,IAAA,CAAC,YAAY,WAAa,EAAA;AAC5B,QAAM,MAAA,IAAI,KAAM,CAAA,CAAA,iCAAA,EAAoC,UAAY,CAAA,CAAA,CAAA,CAAA;AAAA,OAClE;AAEA,MAAQ,KAAA,GAAA;AAAA,QACN,WAAA,EAAa,YAAY,WAAY,CAAA,WAAA;AAAA,QACrC,eAAA,EAAiB,YAAY,WAAY,CAAA,eAAA;AAAA,QACzC,YAAA,EAAc,YAAY,WAAY,CAAA,YAAA;AAAA,OACxC,CAAA;AAAA,aACO,CAAP,EAAA;AACA,MAAQ,OAAA,CAAA,IAAA,CAAK,yCAAyC,CAAG,CAAA,CAAA,CAAA,CAAA;AACzD,MAAM,MAAA,IAAI,KAAM,CAAA,CAAA,uBAAA,EAA0B,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,KAC/C;AACA,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAAA,EACA,MAAM,cAAA,CACJ,WACA,EAAA,UAAA,EACA,UACiB,EAAA;AACjB,IAAA,MAAM,WAAc,GAAA,MAAM,IAAK,CAAA,cAAA,CAAe,YAAY,UAAU,CAAA,CAAA;AAEpE,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,IAAM,EAAA,CAAA,iBAAA,CAAA;AAAA,MACN,IAAM,EAAA,CAAA,8DAAA,CAAA;AAAA,MACN,OAAS,EAAA;AAAA,QACP,cAAgB,EAAA,WAAA;AAAA,OAClB;AAAA,MACA,SAAW,EAAA,IAAA;AAAA,KACb,CAAA;AAEA,IAAM,MAAA,MAAA,GAASE,SAAK,CAAA,OAAA,EAAS,WAAW,CAAA,CAAA;AACxC,IAAA,MAAM,GAAM,GAAA,CAAA,QAAA,EAAW,MAAO,CAAA,IAAA,CAAA,EAAO,MAAO,CAAA,IAAA,CAAA,CAAA,CAAA;AAC5C,IAAA,MAAM,YAAY,MAAO,CAAA,IAAA,CAAK,KAAK,QAAQ,CAAA,CAAE,SAAS,QAAQ,CAAA,CAAA;AAC9D,IAAA,MAAM,gBAAmB,GAAA,SAAA,CACtB,OAAQ,CAAA,KAAA,EAAO,GAAG,CAAA,CAClB,OAAQ,CAAA,KAAA,EAAO,GAAG,CAAA,CAClB,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAA,CAAA;AAEpB,IAAA,OAAO,CAAc,WAAA,EAAA,gBAAA,CAAA,CAAA,CAAA;AAAA,GACvB;AAAA,EAEA,MAAM,+BACJ,cAC4B,EAAA;AAC5B,IAAA,MAAM,8BAAiD,MAAO,CAAA,MAAA;AAAA,MAC5D,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AAEA,IAA4B,2BAAA,CAAA,mBAAA,GAAsB,MAAM,IAAK,CAAA,cAAA;AAAA,MAC3D,cAAe,CAAA,IAAA;AAAA,MACf,cAAe,CAAA,UAAA;AAAA,MACf,cAAe,CAAA,UAAA;AAAA,KACjB,CAAA;AACA,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AACF;;ACjHA,MAAM,QAAW,GAAA,+CAAA,CAAA;AAMV,MAAM,qCAEb,CAAA;AAAA,EAIE,WACmB,CAAA,MAAA,EACA,eAAmC,GAAA,IAAIC,iCACxD,EAAA;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA,CAAA;AALnB,IAAA,IAAA,CAAQ,WAA2B,GAAA,EAAE,KAAO,EAAA,EAAA,EAAI,oBAAoB,CAAE,EAAA,CAAA;AAAA,GAMnE;AAAA,EAEH,MAAM,+BACJ,cAC8B,EAAA;AAC9B,IAAA,MAAM,8BAAmD,MAAO,CAAA,MAAA;AAAA,MAC9D,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AAEA,IAA4B,2BAAA,CAAA,mBAAA,GAAsB,MAAM,IAAA,CAAK,QAAS,EAAA,CAAA;AACtE,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAc,QAA4B,GAAA;AACxC,IAAI,IAAA,CAAC,IAAK,CAAA,oBAAA,EAAwB,EAAA;AAChC,MAAA,OAAO,KAAK,WAAY,CAAA,KAAA,CAAA;AAAA,KAC1B;AAEA,IAAI,IAAA,CAAC,KAAK,eAAiB,EAAA;AACzB,MAAK,IAAA,CAAA,eAAA,GAAkB,KAAK,aAAc,EAAA,CAAA;AAAA,KAC5C;AAEA,IAAA,OAAO,IAAK,CAAA,eAAA,CAAA;AAAA,GACd;AAAA,EAEA,MAAc,aAAiC,GAAA;AAC7C,IAAI,IAAA;AACF,MAAK,IAAA,CAAA,MAAA,CAAO,KAAK,kCAAkC,CAAA,CAAA;AAEnD,MAAA,MAAM,cAAiB,GAAA,MAAM,IAAK,CAAA,eAAA,CAAgB,SAAS,QAAU,EAAA;AAAA,QACnE,cAAA,EAAgB,EAAE,OAAA,EAAS,GAAO,EAAA;AAAA;AAAA,OACnC,CAAA,CAAA;AACD,MAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,QAAM,MAAA,IAAI,MAAM,qBAAqB,CAAA,CAAA;AAAA,OACvC;AAEA,MAAA,IAAA,CAAK,WAAc,GAAA,cAAA,CAAA;AAAA,aACZ,GAAP,EAAA;AACA,MAAK,IAAA,CAAA,MAAA,CAAO,KAAM,CAAA,6BAAA,EAA+B,GAAG,CAAA,CAAA;AAGpD,MAAI,IAAA,IAAA,CAAK,cAAgB,EAAA;AACvB,QAAM,MAAA,GAAA,CAAA;AAAA,OACR;AAAA,KACF;AAEA,IAAA,IAAA,CAAK,eAAkB,GAAA,KAAA,CAAA,CAAA;AACvB,IAAA,OAAO,KAAK,WAAY,CAAA,KAAA,CAAA;AAAA,GAC1B;AAAA,EAEQ,oBAAgC,GAAA;AAEtC,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,WAAY,CAAA,kBAAA,GAAqB,KAAK,EAAK,GAAA,GAAA,CAAA;AAClE,IAAO,OAAA,IAAA,CAAK,KAAS,IAAA,SAAA,CAAA;AAAA,GACvB;AAAA,EAEQ,YAAwB,GAAA;AAC9B,IAAA,OAAO,IAAK,CAAA,GAAA,EAAS,IAAA,IAAA,CAAK,WAAY,CAAA,kBAAA,CAAA;AAAA,GACxC;AACF;;AC5EO,MAAM,8BAEb,CAAA;AAAA,EACE,MAAM,8BACJ,CAAA,cAAA,EACA,UAC4B,EAAA;AAC5B,IAAA,MAAM,8BAAiD,MAAO,CAAA,MAAA;AAAA,MAC5D,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AACA,IAAA,MAAM,YAAgC,UAAW,CAAA,MAAA,CAAA;AAEjD,IAAA,IAAI,SAAW,EAAA;AACb,MAAA,2BAAA,CAA4B,mBAAsB,GAAA,SAAA,CAAA;AAAA,KAC7C,MAAA;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,0DAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AACF;;ACvBO,MAAM,kCAEb,CAAA;AAAA,EACE,MAAM,+BACJ,cAC4B,EAAA;AAC5B,IAAA,MAAM,8BAAiD,MAAO,CAAA,MAAA;AAAA,MAC5D,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AACA,IAAA,MAAM,MAAS,GAAA,IAAIC,oBAAU,CAAA,EAAA,CAAG,oBAAqB,EAAA,CAAA;AACrD,IAAA,MAAM,WAAc,GAAA,MAAM,MAAO,CAAA,IAAA,CAAK,cAAe,EAAA,CAAA;AAErD,IAAA,IAAI,WAAa,EAAA;AACf,MAAA,2BAAA,CAA4B,mBAAsB,GAAA,WAAA,CAAA;AAAA,KAC7C,MAAA;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,sFAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AACF;;ACtBO,MAAM,4BAAiE,CAAA;AAAA,EAC5E,MAAM,+BACJ,cACuC,EAAA;AACvC,IAAO,OAAA,cAAA,CAAA;AAAA,GACT;AACF;;ACLO,MAAM,4BAAiE,CAAA;AAAA,EAC5E,MAAM,8BACJ,CAAA,cAAA,EACA,UACyB,EAAA;AA5B7B,IAAA,IAAA,EAAA,CAAA;AA6BI,IAAA,MAAM,8BAA8C,MAAO,CAAA,MAAA;AAAA,MACzD,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AAEA,IAAM,MAAA,EAAE,mBAAsB,GAAA,cAAA,CAAA;AAE9B,IAAI,IAAA,CAAC,iBAAqB,IAAA,iBAAA,KAAsB,EAAI,EAAA;AAClD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,yDAAA,CAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAM,MAAA,SAAA,GAAA,CAAgC,EAAW,GAAA,UAAA,CAAA,IAAA,KAAX,IAAkB,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,iBAAA,CAAA,CAAA;AAExD,IAAA,IAAI,SAAW,EAAA;AACb,MAAA,2BAAA,CAA4B,mBAAsB,GAAA,SAAA,CAAA;AAAA,KAC7C,MAAA;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAmC,gCAAA,EAAA,iBAAA,CAAA,gBAAA,CAAA;AAAA,OACrC,CAAA;AAAA,KACF;AACA,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AACF;;ACxBO,MAAM,iCAAkC,CAAA;AAAA,EAC7C,OAAO,mCACL,CAAA,YAAA,EACA,OAG0B,EAAA;AAC1B,IAAA,QAAQ,YAAc;AAAA,MACpB,KAAK,QAAU,EAAA;AACb,QAAA,OAAO,IAAI,8BAA+B,EAAA,CAAA;AAAA,OAC5C;AAAA,MACA,KAAK,KAAO,EAAA;AACV,QAAA,OAAO,IAAI,8BAA+B,EAAA,CAAA;AAAA,OAC5C;AAAA,MACA,KAAK,OAAS,EAAA;AACZ,QAAO,OAAA,IAAI,qCAAsC,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA,OACjE;AAAA,MACA,KAAK,gBAAkB,EAAA;AACrB,QAAA,OAAO,IAAI,4BAA6B,EAAA,CAAA;AAAA,OAC1C;AAAA,MACA,KAAK,sBAAwB,EAAA;AAC3B,QAAA,OAAO,IAAI,kCAAmC,EAAA,CAAA;AAAA,OAChD;AAAA,MACA,KAAK,MAAQ,EAAA;AACX,QAAA,OAAO,IAAI,4BAA6B,EAAA,CAAA;AAAA,OAC1C;AAAA,MACA,KAAK,mBAAqB,EAAA;AACxB,QAAA,OAAO,IAAI,4BAA6B,EAAA,CAAA;AAAA,OAC1C;AAAA,MACA,SAAS;AACP,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAiB,cAAA,EAAA,YAAA,CAAA,oDAAA,CAAA;AAAA,SACnB,CAAA;AAAA,OACF;AAAA,KACF;AAAA,GACF;AACF;;AC9CO,MAAM,oBAA2D,CAAA;AAAA,EAGtE,YAAY,cAAkC,EAAA;AAC5C,IAAA,IAAA,CAAK,cAAiB,GAAA,cAAA,CAAA;AAAA,GACxB;AAAA,EAEA,OAAO,WAAW,MAAsC,EAAA;AAGtD,IAAA,OAAO,IAAI,oBAAA;AAAA,MACT,MAAO,CAAA,cAAA,CAAe,UAAU,CAAA,CAAE,IAAI,CAAK,CAAA,KAAA;AA9BjD,QAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AA+BQ,QAAM,MAAA,YAAA,GAAe,CAAE,CAAA,SAAA,CAAU,cAAc,CAAA,CAAA;AAC/C,QAAA,MAAM,cAAiC,GAAA;AAAA,UACrC,IAAA,EAAM,CAAE,CAAA,SAAA,CAAU,MAAM,CAAA;AAAA,UACxB,GAAA,EAAK,CAAE,CAAA,SAAA,CAAU,KAAK,CAAA;AAAA,UACtB,mBAAA,EAAqB,CAAE,CAAA,iBAAA,CAAkB,qBAAqB,CAAA;AAAA,UAC9D,aAAe,EAAA,CAAA,EAAA,GAAA,CAAA,CAAE,kBAAmB,CAAA,eAAe,MAApC,IAAyC,GAAA,EAAA,GAAA,KAAA;AAAA,UACxD,iBAAmB,EAAA,CAAA,EAAA,GAAA,CAAA,CAAE,kBAAmB,CAAA,mBAAmB,MAAxC,IAA6C,GAAA,EAAA,GAAA,KAAA;AAAA,UAChE,MAAA,EAAQ,CAAE,CAAA,iBAAA,CAAkB,QAAQ,CAAA;AAAA,UACpC,MAAA,EAAQ,CAAE,CAAA,iBAAA,CAAkB,QAAQ,CAAA;AAAA,UACpC,YAAA;AAAA,SACF,CAAA;AACA,QAAM,MAAA,YAAA,GAAe,CAAE,CAAA,iBAAA,CAAkB,cAAc,CAAA,CAAA;AACvD,QAAA,IAAI,YAAc,EAAA;AAChB,UAAA,cAAA,CAAe,YAAe,GAAA,YAAA,CAAA;AAAA,SAChC;AACA,QAAM,MAAA,YAAA,GAAe,CAAE,CAAA,iBAAA,CAAkB,cAAc,CAAA,CAAA;AACvD,QAAA,IAAI,YAAc,EAAA;AAChB,UAAA,cAAA,CAAe,YAAe,GAAA,YAAA,CAAA;AAAA,SAChC;AACA,QAAI,IAAA,CAAA,CAAE,GAAI,CAAA,qBAAqB,CAAG,EAAA;AAChC,UAAe,cAAA,CAAA,mBAAA,GAAsB,CAAE,CAAA,GAAA,CAAI,qBAAqB,CAAA,CAAA;AAAA,SAClE;AAEA,QAAA,QAAQ,YAAc;AAAA,UACpB,KAAK,QAAU,EAAA;AACb,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAAA,UACA,KAAK,KAAO,EAAA;AACV,YAAM,MAAA,UAAA,GAAa,CAAE,CAAA,iBAAA,CAAkB,YAAY,CAAA,CAAA;AACnD,YAAM,MAAA,UAAA,GAAa,CAAE,CAAA,iBAAA,CAAkB,YAAY,CAAA,CAAA;AAEnD,YAAA,OAAO,EAAE,UAAA,EAAY,UAAY,EAAA,GAAG,cAAe,EAAA,CAAA;AAAA,WACrD;AAAA,UACA,KAAK,OAAS,EAAA;AACZ,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAAA,UACA,KAAK,MAAQ,EAAA;AACX,YAAM,MAAA,iBAAA,GAAoB,CAAE,CAAA,SAAA,CAAU,mBAAmB,CAAA,CAAA;AAEzD,YAAO,OAAA,EAAE,iBAAmB,EAAA,GAAG,cAAe,EAAA,CAAA;AAAA,WAChD;AAAA,UACA,KAAK,gBAAkB,EAAA;AACrB,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAAA,UACA,KAAK,sBAAwB,EAAA;AAC3B,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAAA,UACA,SAAS;AACP,YAAA,MAAM,IAAI,KAAA;AAAA,cACR,CAAiB,cAAA,EAAA,YAAA,CAAA,kCAAA,CAAA;AAAA,aACnB,CAAA;AAAA,WACF;AAAA,SACF;AAAA,OACD,CAAA;AAAA,KACH,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,WAAyC,GAAA;AAC7C,IAAA,OAAO,IAAK,CAAA,cAAA,CAAA;AAAA,GACd;AACF;;ACjEgB,SAAA,eAAA,CAAgB,IAAe,OAA6B,EAAA;AAC1E,EAAI,IAAA,MAAA,CAAA;AACJ,EAAA,IAAI,SAAY,GAAA,KAAA,CAAA;AAChB,EAAM,MAAA,mBAAA,GAAsB,IAAI,OAAA,CAAc,CAAW,OAAA,KAAA;AACvD,IAAA,MAAA,GAAS,MAAM;AACb,MAAQ,OAAA,EAAA,CAAA;AACR,MAAY,SAAA,GAAA,IAAA,CAAA;AAAA,KACd,CAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,MAAM,eAAe,YAAY;AAC/B,IAAA,OAAO,CAAC,SAAW,EAAA;AACjB,MAAI,IAAA;AACF,QAAA,MAAM,EAAG,EAAA,CAAA;AAAA,OACT,CAAA,MAAA;AAAA,OAEF;AAEA,MAAA,MAAM,QAAQ,IAAK,CAAA;AAAA,QACjB,IAAI,OAAQ,CAAA,CAAA,OAAA,KAAW,UAAW,CAAA,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,QACnD,mBAAA;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,GACF,CAAA;AACA,EAAa,YAAA,EAAA,CAAA;AAEb,EAAO,OAAA,MAAA,CAAA;AACT;;ACZO,MAAM,iBAAwD,CAAA;AAAA,EACnE,YACmB,OACA,EAAA,MAAA,EACT,cAAkD,GAAA,KAAA,CAAA,EAClD,oBAA6B,KACrC,EAAA;AAJiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA,CAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACT,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA,CAAA;AACA,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA,CAAA;AAAA,GACP;AAAA,EAEH,OAAO,oBAAA,CACL,MACA,EAAA,MAAA,EACA,eACmB,EAAA;AArDvB,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AAsDI,IAAA,MAAM,0BACJ,EAAO,GAAA,CAAA,EAAA,GAAA,MAAA,CAAA,sBAAA,CAAuB,wBAAwB,CAAtD,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAyD,IAAI,CAAO,GAAA,KAAA;AAClE,MAAO,OAAA,EAAE,GAAK,EAAA,GAAA,CAAI,SAAU,CAAA,KAAK,GAAG,KAAO,EAAA,GAAA,CAAI,SAAU,CAAA,OAAO,CAAE,EAAA,CAAA;AAAA,KACpE,CAAA,KAFA,YAEM,EAAC,CAAA;AAET,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,SAAA,EAAW,MAAO,CAAA,SAAA,CAAU,WAAW,CAAA;AAAA,MACvC,MAAQ,EAAA,CAAA,EAAA,GAAA,MAAA,CAAO,iBAAkB,CAAA,QAAQ,MAAjC,IAAsC,GAAA,EAAA,GAAA,GAAA;AAAA,MAC9C,aAAe,EAAA,CAAA,EAAA,GAAA,MAAA,CAAO,kBAAmB,CAAA,eAAe,MAAzC,IAA8C,GAAA,EAAA,GAAA,KAAA;AAAA,MAC7D,iBACE,EAAA,CAAA,EAAA,GAAA,MAAA,CAAO,kBAAmB,CAAA,mBAAmB,MAA7C,IAAkD,GAAA,EAAA,GAAA,KAAA;AAAA,MACpD,eAAiB,EAAA,CAAA,EAAA,GAAA,MAAA,CAAO,kBAAmB,CAAA,iBAAiB,MAA3C,IAAgD,GAAA,EAAA,GAAA,KAAA;AAAA,MACjE,sBAAA;AAAA,KACF,CAAA;AACA,IAAA,MAAM,iBAAoB,GAAA,IAAI,iBAAkB,CAAA,OAAA,EAAS,MAAM,CAAA,CAAA;AAC/D,IAAA,IAAI,eAAiB,EAAA;AACnB,MAAA,eAAA;AAAA,QACE,MAAM,kBAAkB,eAAgB,EAAA;AAAA,QACxC,gBAAgB,QAAS,EAAA;AAAA,OAC3B,CAAA;AAAA,KACF;AACA,IAAO,OAAA,iBAAA,CAAA;AAAA,GACT;AAAA,EAEA,OAAO,UAAA,CACL,MACA,EAAA,eAAA,GAAwC,KACrB,CAAA,EAAA;AACnB,IAAA,OAAO,iBAAkB,CAAA,oBAAA;AAAA,MACvB,MAAA;AAAA,MACA,IAAIA,oBAAU,CAAA,EAAA,CAAG,oBAAqB,EAAA;AAAA,MACtC,eAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,WAAyC,GAAA;AAzFjD,IAAA,IAAA,EAAA,CAAA;AA0FI,IAAI,IAAA,CAAC,KAAK,iBAAmB,EAAA;AAE3B,MAAA,MAAM,KAAK,eAAgB,EAAA,CAAA;AAAA,KAC7B;AACA,IAAO,OAAA,CAAA,EAAA,GAAA,IAAA,CAAK,cAAL,KAAA,IAAA,GAAA,EAAA,GAAuB,EAAC,CAAA;AAAA,GACjC;AAAA;AAAA,EAGA,MAAM,eAAiC,GAAA;AAlGzC,IAAA,IAAA,EAAA,CAAA;AAmGI,IAAM,MAAA;AAAA,MACJ,SAAA;AAAA,MACA,MAAA;AAAA,MACA,aAAA;AAAA,MACA,iBAAA;AAAA,MACA,eAAA;AAAA,MACA,sBAAA;AAAA,QACE,IAAK,CAAA,OAAA,CAAA;AACT,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,MAAA,EAAQ,YAAY,SAAuB,CAAA,WAAA,EAAA,MAAA,CAAA,CAAA;AAAA,KAC7C,CAAA;AAEA,IAAI,IAAA;AACF,MAAA,MAAM,CAAC,QAAQ,CAAA,GAAI,MAAM,IAAK,CAAA,MAAA,CAAO,aAAa,OAAO,CAAA,CAAA;AACzD,MAAA,IAAA,CAAK,mBAAkB,EAAS,GAAA,QAAA,CAAA,QAAA,KAAT,YAAqB,EAAC,EAC1C,OAAO,CAAK,CAAA,KAAA;AACX,QAAO,OAAA,sBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,sBAAA,CAAwB,MAAM,CAAO,GAAA,KAAA;AAC1C,UAAI,IAAA,CAAC,EAAE,cAAgB,EAAA;AACrB,YAAO,OAAA,KAAA,CAAA;AAAA,WACT;AACA,UAAA,OAAO,CAAE,CAAA,cAAA,CAAe,GAAI,CAAA,GAAG,MAAM,GAAI,CAAA,KAAA,CAAA;AAAA,SAC3C,CAAA,CAAA;AAAA,OACD,CACA,CAAA,GAAA,CAAI,CAAE,CAAA,KAAA;AA1Hf,QAAA,IAAAC,GAAA,EAAA,EAAA,CAAA;AA0HmB,QAAA,OAAA;AAAA;AAAA,UAET,IAAMA,EAAAA,CAAAA,GAAAA,GAAA,CAAE,CAAA,IAAA,KAAF,OAAAA,GAAU,GAAA,SAAA;AAAA,UAChB,GAAK,EAAA,CAAA,QAAA,EAAA,CAAW,EAAE,GAAA,CAAA,CAAA,QAAA,KAAF,IAAc,GAAA,EAAA,GAAA,EAAA,CAAA,CAAA;AAAA,UAC9B,YAAc,EAAA,QAAA;AAAA,UACd,aAAA;AAAA,UACA,iBAAA;AAAA,UACA,GAAI,eACA,GAAA;AAAA,YACE,YAAc,EAAA,KAAA;AAAA,YACd,mBAAqB,EAAA;AAAA,cACnB,SAAA;AAAA,cACA,MAAA;AAAA,cACA,aAAa,CAAE,CAAA,IAAA;AAAA,aACjB;AAAA,cAEF,EAAC;AAAA,SACP,CAAA;AAAA,OAAE,CAAA,CAAA;AACJ,MAAA,IAAA,CAAK,iBAAoB,GAAA,IAAA,CAAA;AAAA,aAClB,CAAP,EAAA;AACA,MAAA,MAAM,IAAIC,qBAAA;AAAA,QACR,iEAAiE,SAAoB,CAAA,QAAA,EAAA,MAAA,CAAA,CAAA;AAAA,QACrF,CAAA;AAAA,OACF,CAAA;AAAA,KACF;AAAA,GACF;AACF;;ACvHO,MAAM,qBAA4D,CAAA;AAAA,EAGvE,YAAY,aAA2B,EAAA;AACrC,IAAA,IAAA,CAAK,aAAgB,GAAA,aAAA,CAAA;AAAA,GACvB;AAAA,EAEA,OAAO,WAAW,UAA+C,EAAA;AAC/D,IAAO,OAAA,IAAI,sBAAsB,UAAU,CAAA,CAAA;AAAA,GAC7C;AAAA,EAEA,MAAM,WAAyC,GAAA;AAC7C,IAAA,MAAM,eAAe,CAAwB,qBAAA,EAAAC,uDAAA,CAAA,CAAA,CAAA;AAC7C,IAAA,MAAM,iBAAiB,CAAwB,qBAAA,EAAAC,0DAAA,CAAA,CAAA,CAAA;AAC/C,IAAA,MAAM,kBAAkB,CAAwB,qBAAA,EAAAC,0DAAA,CAAA,CAAA,CAAA;AAEhD,IAAA,MAAM,MAA0C,GAAA;AAAA,MAC9C,IAAM,EAAA,UAAA;AAAA,MACN,WAAa,EAAA,oBAAA;AAAA,MACb,CAAC,YAAY,GAAGC,mCAAA;AAAA,MAChB,CAAC,cAAc,GAAGA,mCAAA;AAAA,MAClB,CAAC,eAAe,GAAGA,mCAAA;AAAA,KACrB,CAAA;AAEA,IAAA,MAAM,QAAW,GAAA,MAAM,IAAK,CAAA,aAAA,CAAc,WAAY,CAAA;AAAA,MACpD,MAAA,EAAQ,CAAC,MAAM,CAAA;AAAA,KAChB,CAAA,CAAA;AACD,IAAO,OAAA,QAAA,CAAS,KAAM,CAAA,GAAA,CAAI,CAAU,MAAA,KAAA;AAClC,MAAA,MAAM,cAAiC,GAAA;AAAA,QACrC,IAAA,EAAM,OAAO,QAAS,CAAA,IAAA;AAAA,QACtB,GAAK,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaH,uDAAgC,CAAA;AAAA,QAClE,MACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaC,0DAAmC,CAAA;AAAA,QAClE,YACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaC,0DAAmC,CAAA;AAAA,QAClE,iBACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CACdE,gEACF,CAAA;AAAA,QACF,mBACE,MAAO,CAAA,QAAA,CAAS,YACdC,gEACF,CAAA,KAAO,SACH,IACA,GAAA,KAAA;AAAA,QACN,eACE,MAAO,CAAA,QAAA,CAAS,YACdC,4DACF,CAAA,KAAO,SACH,IACA,GAAA,KAAA;AAAA,QACN,YACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaC,0DAAmC,CAAA;AAAA,QAClE,YACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaC,0DAAmC,CAAA;AAAA,OACpE,CAAA;AAEA,MAAO,OAAA,cAAA,CAAA;AAAA,KACR,CAAA,CAAA;AAAA,GACH;AACF;;ACvEO,MAAM,+BAEb,CAAA;AAAA,EAGS,WAAc,GAAA;AACnB,IAAA,IAAA,CAAK,cAAiB,GAAA;AAAA,MACpB;AAAA,QACE,IAAM,EAAA,OAAA;AAAA,QACN,GAAK,EAAA,sBAAA;AAAA,QACL,YAAc,EAAA,mBAAA;AAAA,QACd,iBAAmB,EAAA,IAAA;AAAA,OACrB;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,WAAyC,GAAA;AAC7C,IAAA,OAAO,IAAK,CAAA,cAAA,CAAA;AAAA,GACd;AACF;;ACZA,MAAM,wBAA+D,CAAA;AAAA,EACnE,YAAqB,gBAAgD,EAAA;AAAhD,IAAA,IAAA,CAAA,gBAAA,GAAA,gBAAA,CAAA;AAAA,GAAiD;AAAA,EAEtE,MAAM,WAAyC,GAAA;AAC7C,IAAA,OAAO,MAAM,OAAQ,CAAA,GAAA;AAAA,MACnB,KAAK,gBAAiB,CAAA,GAAA,CAAI,CAAY,QAAA,KAAA,QAAA,CAAS,aAAa,CAAA;AAAA,KAC9D,CACG,KAAK,CAAO,GAAA,KAAA;AACX,MAAA,OAAO,IAAI,IAAK,EAAA,CAAA;AAAA,KACjB,CACA,CAAA,KAAA,CAAM,CAAK,CAAA,KAAA;AACV,MAAM,MAAA,CAAA,CAAA;AAAA,KACP,CAAA,CAAA;AAAA,GACL;AACF,CAAA;AAEO,MAAM,0BAA6B,GAAA,CACxC,UACA,EAAA,aAAA,EACA,kBAAwC,KACT,CAAA,KAAA;AAC/B,EAAA,MAAM,mBAAmB,UACtB,CAAA,cAAA,CAAe,kCAAkC,CAAA,CACjD,IAAI,CAAwB,oBAAA,KAAA;AAC3B,IAAM,MAAA,IAAA,GAAO,oBAAqB,CAAA,SAAA,CAAU,MAAM,CAAA,CAAA;AAClD,IAAA,QAAQ,IAAM;AAAA,MACZ,KAAK,SAAA;AACH,QAAO,OAAA,qBAAA,CAAsB,WAAW,aAAa,CAAA,CAAA;AAAA,MACvD,KAAK,mBAAA;AACH,QAAA,OAAO,IAAI,+BAAgC,EAAA,CAAA;AAAA,MAC7C,KAAK,QAAA;AACH,QAAO,OAAA,oBAAA,CAAqB,WAAW,oBAAoB,CAAA,CAAA;AAAA,MAC7D,KAAK,KAAA;AACH,QAAA,OAAO,iBAAkB,CAAA,UAAA;AAAA,UACvB,oBAAA;AAAA,UACA,eAAA;AAAA,SACF,CAAA;AAAA,MACF;AACE,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAkD,+CAAA,EAAA,IAAA,CAAA,CAAA,CAAA;AAAA,SACpD,CAAA;AAAA,KACJ;AAAA,GACD,CAAA,CAAA;AAEH,EAAO,OAAA,IAAI,yBAAyB,gBAAgB,CAAA,CAAA;AACtD,CAAA;;AC5CO,MAAM,yBAA4B,GAAA,CACvC,MACA,EAAA,UAAA,EACA,eACG,KAAA;AACH,EAAM,MAAA,cAAA,GAAiB,OAAO,GAAsB,KAAA;AAClD,IAAM,MAAA,YAAA,GAAe,IAAI,IAAK,CAAA,SAAA,CAAA;AAC9B,IAAI,IAAA,YAAA,IAAgB,OAAO,YAAA,KAAiB,QAAU,EAAA;AACpD,MAAM,MAAA,IAAIC,kBAAW,CAA+B,6BAAA,CAAA,CAAA,CAAA;AAAA,KACtD,MAAA,IAAW,CAAC,YAAc,EAAA;AACxB,MAAM,MAAA,IAAIA,kBAAW,4BAA4B,CAAA,CAAA;AAAA,KACnD;AACA,IAAA,IAAI,SAA2C,GAAA,KAAA,CAAA,CAAA;AAE/C,IAAI,IAAA;AACF,MAAA,SAAA,GAAYC,4BAAe,YAAY,CAAA,CAAA;AAAA,aAChC,KAAP,EAAA;AACA,MAAM,MAAA,IAAID,iBAAW,CAAA,CAAA,oBAAA,EAAuB,KAAO,CAAA,CAAA,CAAA,CAAA;AAAA,KACrD;AAEA,IAAA,MAAM,KAAQ,GAAAE,oDAAA;AAAA,MACZ,IAAI,OAAQ,CAAA,aAAA;AAAA,KACd,CAAA;AAEA,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAM,MAAA,IAAIC,2BAAoB,oBAAoB,CAAA,CAAA;AAAA,KACpD;AAEA,IAAA,MAAM,MAAS,GAAA,MAAM,UAAW,CAAA,cAAA,CAAe,SAAW,EAAA;AAAA,MACxD,KAAA;AAAA,KACD,CAAA,CAAA;AAED,IAAA,IAAI,CAAC,MAAQ,EAAA;AACX,MAAA,MAAM,IAAIH,iBAAA;AAAA,QACR,CAAA,oBAAA,EAAuBI,gCAAmB,SAAS,CAAA,CAAA,CAAA;AAAA,OACrD,CAAA;AAAA,KACF;AACA,IAAO,OAAA,MAAA,CAAA;AAAA,GACT,CAAA;AAEA,EAAA,MAAA,CAAO,IAAK,CAAA,4BAAA,EAA8B,OAAO,GAAA,EAAK,GAAQ,KAAA;AAC5D,IAAM,MAAA,MAAA,GAAS,MAAM,cAAA,CAAe,GAAG,CAAA,CAAA;AACvC,IAAM,MAAA,QAAA,GAAW,MAAM,eAAA,CAAgB,4BAA6B,CAAA;AAAA,MAClE,MAAA;AAAA,MACA,IAAA,EAAM,IAAI,IAAK,CAAA,IAAA;AAAA,KAChB,CAAA,CAAA;AACD,IAAA,GAAA,CAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,GAClB,CAAA,CAAA;AAED,EAAA,MAAA,CAAO,IAAK,CAAA,yBAAA,EAA2B,OAAO,GAAA,EAAK,GAAQ,KAAA;AACzD,IAAM,MAAA,MAAA,GAAS,MAAM,cAAA,CAAe,GAAG,CAAA,CAAA;AAEvC,IAAI,IAAA,CAAC,GAAI,CAAA,IAAA,CAAK,eAAiB,EAAA;AAC7B,MAAM,MAAA,IAAIJ,kBAAW,qCAAqC,CAAA,CAAA;AAAA,eACjD,CAAC,KAAA,CAAM,QAAQ,GAAI,CAAA,IAAA,CAAK,eAAe,CAAG,EAAA;AACnD,MAAM,MAAA,IAAIA,kBAAW,kCAAkC,CAAA,CAAA;AAAA,KAC9C,MAAA,IAAA,GAAA,CAAI,IAAK,CAAA,eAAA,CAAgB,WAAW,CAAG,EAAA;AAChD,MAAM,MAAA,IAAIA,kBAAW,uCAAuC,CAAA,CAAA;AAAA,KAC9D;AAEA,IAAM,MAAA,QAAA,GAAW,MAAM,eAAA,CAAgB,0BAA2B,CAAA;AAAA,MAChE,MAAA;AAAA,MACA,eAAA,EAAiB,IAAI,IAAK,CAAA,eAAA;AAAA,MAC1B,IAAA,EAAM,IAAI,IAAK,CAAA,IAAA;AAAA,KAChB,CAAA,CAAA;AACD,IAAA,GAAA,CAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,GAClB,CAAA,CAAA;AACH,CAAA;;ACnEO,MAAM,yBAA8D,CAAA;AAAA,EAGzE,YAAY,eAA6C,EAAA;AACvD,IAAA,IAAA,CAAK,eAAkB,GAAA,eAAA,CAAA;AAAA,GACzB;AAAA;AAAA,EAGA,mBAAA,CACE,SACA,eACyC,EAAA;AACzC,IAAO,OAAA,IAAA,CAAK,gBAAgB,WAAY,EAAA,CAAE,KAAK,CAAa,QAAA,MAAA,EAAE,UAAW,CAAA,CAAA,CAAA;AAAA,GAC3E;AACF;;ACWA,MAAM,UAAa,GAAA,CACjB,KACmC,KAAA,KAAA,CAAM,MAAW,KAAA,UAAA,CAAA;AAEtD,MAAM,WAAc,GAAA,CAClB,KACuC,KAAA,KAAA,CAAM,MAAW,KAAA,WAAA,CAAA;AAMnD,MAAM,eAAmC,GAAA;AAAA,EAC9C;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,MAAA;AAAA,IACR,UAAY,EAAA,MAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,UAAA;AAAA,IACR,UAAY,EAAA,UAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,YAAA;AAAA,IACR,UAAY,EAAA,YAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,aAAA;AAAA,IACR,UAAY,EAAA,aAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,aAAA;AAAA,IACR,UAAY,EAAA,aAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,aAAA;AAAA,IACR,UAAY,EAAA,aAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,aAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,0BAAA;AAAA,IACR,UAAY,EAAA,0BAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,OAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,MAAA;AAAA,IACR,UAAY,EAAA,MAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,OAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,UAAA;AAAA,IACR,UAAY,EAAA,UAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,mBAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,WAAA;AAAA,IACR,UAAY,EAAA,WAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,cAAA;AAAA,IACR,UAAY,EAAA,cAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,YAAA;AAAA,IACR,UAAY,EAAA,YAAA;AAAA,GACd;AACF,EAAA;AAOA,MAAM,kBAAqB,GAAA,CAAC,EAC1B,KAAA,EAAA,CAAG,IAAS,KAAA,MAAA,CAAA;AACd,MAAM,QAAA,GAAW,CAAC,GAAA,KAA2C,GAAQ,KAAA,KAAA,CAAA,CAAA;AAErE,MAAM,8BAAA,GAAiC,CACrC,KACoB,KAAA;AACpB,EAAA,OAAO,OAAO,KAAA,KAAU,QAAW,GAAA,KAAA,CAAM,UAAc,GAAA,KAAA,CAAA;AACzD,CAAA,CAAA;AAEA,MAAM,oBAAA,GAAuB,CAC3B,OAC+B,KAAA;AAC/B,EAAO,OAAA;AAAA,IACL,YAAA,EAAc,8BAA+B,CAAA,OAAA,CAAQ,YAAY,CAAA;AAAA,IACjE,YAAA,EAAc,8BAA+B,CAAA,OAAA,CAAQ,YAAY,CAAA;AAAA,IACjE,UAAA,EAAY,8BAA+B,CAAA,OAAA,CAAQ,UAAU,CAAA;AAAA,GAC/D,CAAA;AACF,CAAA,CAAA;AAEA,MAAM,qBAAA,GAAwB,CAC5B,SAC0B,KAAA;AAC1B,EAAO,OAAA;AAAA,IACL,WAAW,SAAU,CAAA,SAAA;AAAA,IACrB,QAAA,EAAU,oBAAqB,CAAA,SAAA,CAAU,QAAQ,CAAA;AAAA,IACjD,WAAA,EAAa,oBAAqB,CAAA,SAAA,CAAU,WAAW,CAAA;AAAA,GACzD,CAAA;AACF,CAAA,CAAA;AAEA,MAAM,sBAAA,GAAyB,CAC7B,UACsB,KAAA;AACtB,EAAO,OAAA,UAAA,CACJ,GAAI,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,SAAS,EACpB,IAAK,EAAA,CACL,GAAI,CAAA,CAAC,EAAmC,KAAA;AACvC,IAAO,OAAA;AAAA,MACL,KAAK,EAAG,CAAA,GAAA;AAAA,MACR,MAAA,EAAQ,oBAAqB,CAAA,EAAA,CAAG,MAAM,CAAA;AAAA,MACtC,GAAA,EAAK,oBAAqB,CAAA,EAAA,CAAG,GAAG,CAAA;AAAA,MAChC,UAAY,EAAA,EAAA,CAAG,UAAW,CAAA,GAAA,CAAI,qBAAqB,CAAA;AAAA,KACrD,CAAA;AAAA,GACD,CAAA,CAAA;AACL,CAAA,CAAA;AAIO,MAAM,uBAAwB,CAAA;AAAA,EAQnC,WAAY,CAAA;AAAA,IACV,MAAA;AAAA,IACA,OAAA;AAAA,IACA,cAAA;AAAA,IACA,eAAA;AAAA,IACA,kBAAqB,GAAA,eAAA;AAAA,GACY,EAAA;AACjC,IAAA,IAAA,CAAK,MAAS,GAAA,MAAA,CAAA;AACd,IAAA,IAAA,CAAK,OAAU,GAAA,OAAA,CAAA;AACf,IAAA,IAAA,CAAK,cAAiB,GAAA,cAAA,CAAA;AACtB,IAAA,IAAA,CAAK,eAAkB,GAAA,eAAA,CAAA;AACvB,IAAK,IAAA,CAAA,kBAAA,GAAqB,IAAI,GAAA,CAAI,kBAAkB,CAAA,CAAA;AACpD,IAAA,IAAA,CAAK,kBAAkB,EAAC,CAAA;AAAA,GAC1B;AAAA,EAEA,MAAM,0BAA2B,CAAA;AAAA,IAC/B,MAAA;AAAA,IACA,IAAA;AAAA,IACA,eAAA;AAAA,GAC4D,EAAA;AAE5D,IAAA,OAAO,IAAK,CAAA,cAAA;AAAA,MACV,MAAA;AAAA,MACA,IAAA;AAAA,0BACI,GAAmB,EAAA;AAAA,MACvB,eAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,4BAA6B,CAAA;AAAA,IACjC,MAAA;AAAA,IACA,IAAA;AAAA,GAC8D,EAAA;AAC9D,IAAA,OAAO,IAAK,CAAA,cAAA,CAAe,MAAQ,EAAA,IAAA,EAAM,KAAK,kBAAkB,CAAA,CAAA;AAAA,GAClE;AAAA,EAEA,MAAc,cAAA,CACZ,MACA,EAAA,IAAA,EACA,oBACA,eACA,EAAA;AAhPJ,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AAiPI,IAAM,MAAA,UAAA,GAAA,CAAA,CACJ,kBAAO,QAAP,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAiB,gBAAjB,IAA+B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,4BAAA,CAAA,MAAA,CAC/B,EAAO,GAAA,MAAA,CAAA,QAAA,KAAP,IAAiB,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA,CAAA;AAEnB,IAAA,MAAM,8BACJ,GAAA,MAAM,IAAK,CAAA,8BAAA,CAA+B,QAAQ,IAAM,EAAA;AAAA,MACtD,kBAAA;AAAA,MACA,eAAA,EAAiB,4CAAmB,EAAC;AAAA,KACtC,CAAA,CAAA;AAEH,IAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,MACV,CAAA,qBAAA,EAAwB,8BAA8B,8BACnD,CAAA,GAAA,CAAI,OAAK,CAAE,CAAA,IAAI,CACf,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA,CAAA,CAAA;AAAA,KACd,CAAA;AAEA,IAAA,MAAM,kBACJ,EAAO,GAAA,CAAA,EAAA,GAAA,MAAA,CAAA,QAAA,KAAP,mBAAiB,WAAjB,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CACE,8CACG,CAA8B,2BAAA,EAAA,UAAA,CAAA,CAAA,CAAA;AAErC,IAAA,MAAM,SACJ,GAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,MAAA,CAAO,QAAP,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAiB,gBAAjB,IAA+B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,mCAAA,CAAA,CAAA;AAEjC,IAAA,OAAO,OAAQ,CAAA,GAAA;AAAA,MACb,8BAAA,CAA+B,IAAI,CAAsB,kBAAA,KAAA;AACvD,QAAO,OAAA,IAAA,CAAK,QACT,sBAAuB,CAAA;AAAA,UACtB,SAAW,EAAA,UAAA;AAAA,UACX,cAAgB,EAAA,kBAAA;AAAA,UAChB,kBAAA;AAAA,UACA,aAAA;AAAA,UACA,kBACE,eACA,IAAA,kBAAA,CAAmB,mBACnB,IAAK,CAAA,eAAA,EACL,IAAI,CAAM,CAAA,MAAA;AAAA,YACV,GAAG,CAAA;AAAA,YACH,UAAY,EAAA,iBAAA;AAAA,WACZ,CAAA,CAAA;AAAA,UACF,SAAA;AAAA,SACD,EACA,IAAK,CAAA,CAAA,MAAA,KAAU,KAAK,iBAAkB,CAAA,kBAAA,EAAoB,MAAM,CAAC,CACjE,CAAA,KAAA;AAAA,UACC,CAAC,CACC,KAAA,CAAA,CAAE,IAAS,KAAA,YAAA,GACP,QAAQ,OAAQ,CAAA;AAAA,YACd;AAAA,cACE,MAAQ,EAAA;AAAA,gBACN,EAAE,SAAA,EAAW,aAAe,EAAA,OAAA,EAAS,EAAE,OAAQ,EAAA;AAAA,eACjD;AAAA,cACA,WAAW,EAAC;AAAA,aACd;AAAA,YACA,EAAC;AAAA,WACF,CAAA,GACD,OAAQ,CAAA,MAAA,CAAO,CAAC,CAAA;AAAA,UAEvB,IAAK,CAAA,CAAA,CAAA,KAAK,KAAK,gBAAiB,CAAA,kBAAA,EAAoB,CAAC,CAAC,CAAA,CAAA;AAAA,OAC1D,CAAA;AAAA,KACH,CAAE,IAAK,CAAA,IAAA,CAAK,yBAAyB,CAAA,CAAA;AAAA,GACvC;AAAA,EAEA,MAAc,8BAAA,CACZ,MACA,EAAA,IAAA,EACA,cACA,EAAA;AACA,IAAA,MAAM,kBACJ,MAAM,IAAA,CAAK,eAAe,mBAAoB,CAAA,MAAA,EAAQ,cAAc,CACpE,EAAA,QAAA,CAAA;AAGF,IAAM,MAAA,cAAA,GAAiB,MAAM,OAAQ,CAAA,UAAA;AAAA,MACnC,cAAA,CAAe,IAAI,CAAM,EAAA,KAAA;AACvB,QAAA,MAAM,wBACJ,GAAA,IAAA,CAAK,iBAAkB,CAAA,EAAA,CAAG,YAAY,CAAA,CAAA;AACxC,QAAA,OAAO,wBAAyB,CAAA,8BAAA;AAAA,UAC9B,EAAA;AAAA,UACA,IAAA;AAAA,SACF,CAAA;AAAA,OACD,CAAA;AAAA,KACH,CAAA;AAEA,IAAA,cAAA,CAAe,MAAO,CAAA,UAAU,CAAE,CAAA,GAAA,CAAI,CAAQ,IAAA,KAAA;AAC5C,MAAA,IAAA,CAAK,MAAO,CAAA,IAAA,CAAK,CAAuC,oCAAA,EAAA,IAAA,CAAK,MAAQ,CAAA,CAAA,CAAA,CAAA;AAAA,KACtE,CAAA,CAAA;AACD,IAAA,OAAO,eAAe,MAAO,CAAA,WAAW,EAAE,GAAI,CAAA,CAAA,IAAA,KAAQ,KAAK,KAAK,CAAA,CAAA;AAAA,GAClE;AAAA,EAEA,0BACE,cACyB,EAAA;AACzB,IAAO,OAAA;AAAA,MACL,OAAO,cAAe,CAAA,MAAA;AAAA,QACpB,UACG,IAAK,CAAA,MAAA,KAAW,UAAa,IAAK,CAAA,MAAA,CAAO,UAAU,CACnD,IAAA,IAAA,CAAK,SAAc,KAAA,KAAA,CAAA,IAClB,KAAK,SAAU,CAAA,MAAA,IAAU,KACzB,IAAK,CAAA,SAAA,CAAU,KAAK,CAAG,EAAA,KAAA;AAnVnC,UAAA,IAAA,EAAA,CAAA;AAmVsC,UAAG,OAAA,CAAA,CAAA,EAAA,GAAA,EAAA,CAAA,SAAA,KAAH,mBAAc,MAAU,KAAA,CAAA,CAAA;AAAA,SAAC,CAAA;AAAA,OACzD;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,gBACE,CAAA,cAAA,EACA,CAAC,MAAA,EAAQ,OAAO,CACA,EAAA;AAChB,IAAA,MAAM,OAA0B,GAAA;AAAA,MAC9B,OAAS,EAAA;AAAA,QACP,MAAM,cAAe,CAAA,IAAA;AAAA,OACvB;AAAA,MACA,UAAA,EAAY,uBAAuB,OAAO,CAAA;AAAA,MAC1C,WAAW,MAAO,CAAA,SAAA;AAAA,MAClB,QAAQ,MAAO,CAAA,MAAA;AAAA,KACjB,CAAA;AACA,IAAA,IAAI,eAAe,YAAc,EAAA;AAC/B,MAAQ,OAAA,CAAA,OAAA,CAAQ,eAAe,cAAe,CAAA,YAAA,CAAA;AAAA,KAChD;AACA,IAAA,IAAI,eAAe,YAAc,EAAA;AAC/B,MAAQ,OAAA,CAAA,OAAA,CAAQ,eAAe,cAAe,CAAA,YAAA,CAAA;AAAA,KAChD;AACA,IAAA,IAAI,eAAe,mBAAqB,EAAA;AACtC,MAAQ,OAAA,CAAA,OAAA,CAAQ,sBAAsB,cAAe,CAAA,mBAAA,CAAA;AAAA,KACvD;AACA,IAAO,OAAA,OAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAM,iBACJ,CAAA,cAAA,EACA,MAC8B,EAAA;AAC9B,IAAA,IAAI,eAAe,iBAAmB,EAAA;AACpC,MAAO,OAAA,CAAC,MAAQ,EAAA,EAAE,CAAA,CAAA;AAAA,KACpB;AACA,IAAA,MAAM,aAA0B,IAAI,GAAA;AAAA,MAClC,MAAA,CAAO,SACJ,CAAA,MAAA,CAAO,kBAAkB,CAAA,CACzB,OAAQ,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,SAAS,CACxB,CAAA,GAAA,CAAI,CAAE,CAAA,KAAA;AA3Xf,QAAA,IAAA,EAAA,CAAA;AA2XkB,QAAA,OAAA,CAAA,EAAA,GAAA,CAAA,CAAE,aAAF,IAAY,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,SAAA,CAAA;AAAA,OAAS,CAAA,CAC9B,OAAO,QAAQ,CAAA;AAAA,KACpB,CAAA;AAEA,IAAI,IAAA,UAAA,CAAW,SAAS,CAAG,EAAA;AACzB,MAAO,OAAA,CAAC,MAAQ,EAAA,EAAE,CAAA,CAAA;AAAA,KACpB;AAEA,IAAM,MAAA,UAAA,GAAa,MAAM,IAAA,CAAK,OAAQ,CAAA,2BAAA;AAAA,MACpC,cAAA;AAAA,MACA,UAAA;AAAA,KACF,CAAA;AAEA,IAAA,MAAA,CAAO,MAAO,CAAA,IAAA,CAAK,GAAG,UAAA,CAAW,MAAM,CAAA,CAAA;AACvC,IAAO,OAAA,CAAC,MAAQ,EAAA,UAAA,CAAW,SAAqC,CAAA,CAAA;AAAA,GAClE;AAAA,EAEQ,kBAAkB,QAA4C,EAAA;AACpE,IAAI,IAAA,IAAA,CAAK,eAAgB,CAAA,QAAQ,CAAG,EAAA;AAClC,MAAO,OAAA,IAAA,CAAK,gBAAgB,QAAQ,CAAA,CAAA;AAAA,KACtC;AAEA,IAAK,IAAA,CAAA,eAAA,CAAgB,QAAQ,CAAA,GAC3B,iCAAkC,CAAA,mCAAA;AAAA,MAChC,QAAA;AAAA,MACA;AAAA,QACE,QAAQ,IAAK,CAAA,MAAA;AAAA,OACf;AAAA,KACF,CAAA;AACF,IAAO,OAAA,IAAA,CAAK,gBAAgB,QAAQ,CAAA,CAAA;AAAA,GACtC;AACF;;ACxWA,MAAM,OAAU,GAAA,CAAC,EACf,KAAA,EAAA,CAAG,eAAe,WAAW,CAAA,CAAA;AAE/B,SAAS,8BACP,OACsB,EAAA;AAvDxB,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAwDE,EAAA,MAAM,OAAqC,GAAAK,0BAAA,CAAO,OAAQ,CAAA,OAAA,EAAS,CAAS,KAAA,KAAA;AAC1E,IAAO,OAAA,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAW,GAAA,WAAA,CAAA;AAAA,GACpC,CAAA,CAAA;AAED,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,CAAA,EAAA,GAAA,OAAA,CAAQ,MAAR,KAAA,IAAA,GAAA,EAAA,GAAkB,EAAC;AAAA,IAC3B,SAAW,EAAA,CAAA,EAAA,GAAA,OAAA,CAAQ,SAAR,KAAA,IAAA,GAAA,EAAA,GAAqB,EAAC;AAAA,GACnC,CAAA;AACF,CAAA;AAEA,MAAM,qBAAA,GAAwB,CAAC,UAA6C,KAAA;AAC1E,EAAA,QAAQ,UAAY;AAAA,IAClB,KAAK,GAAA;AACH,MAAO,OAAA,aAAA,CAAA;AAAA,IACT,KAAK,GAAA;AACH,MAAO,OAAA,oBAAA,CAAA;AAAA,IACT,KAAK,GAAA;AACH,MAAO,OAAA,WAAA,CAAA;AAAA,IACT,KAAK,GAAA;AACH,MAAO,OAAA,cAAA,CAAA;AAAA,IACT;AACE,MAAO,OAAA,eAAA,CAAA;AAAA,GACX;AACF,CAAA,CAAA;AAEO,MAAM,4BAA0D,CAAA;AAAA,EAGrE,WAAA,CAAY,EAAE,MAAA,EAA+C,EAAA;AAC3D,IAAA,IAAA,CAAK,MAAS,GAAA,MAAA,CAAA;AAAA,GAChB;AAAA,EAEA,uBACE,MAC+B,EAAA;AAC/B,IAAM,MAAA,YAAA,GAAe,MAAM,IAAK,CAAA,MAAA,CAAO,kBAAkB,CACtD,CAAA,MAAA,CAAO,MAAO,CAAA,eAAe,CAC7B,CAAA,GAAA;AAAA,MAAI,CAAC,EAAE,UAAA,EAAY,OAAO,UAAY,EAAA,MAAA,OACrC,IAAK,CAAA,aAAA;AAAA,QACH,MAAO,CAAA,cAAA;AAAA,QACP,KAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAO,CAAA,SAAA;AAAA,QACP,MAAA,CAAO,aACL,IAAA,CAAA,2BAAA,EAA8B,MAAO,CAAA,SAAA,CAAA,CAAA;AAAA,OACvC,CAAA,IAAA;AAAA,QACA,CAAC,CACC,KAAA,CAAA,CAAE,EACE,GAAA,CAAA,CAAE,MAAO,CAAA,IAAA;AAAA,UACP,CAAC,EAAE,KAAA,EAA4B,MAAA;AAAA,YAC7B,IAAM,EAAA,UAAA;AAAA,YACN,SAAW,EAAA,KAAA;AAAA,WACb,CAAA;AAAA,YAEF,IAAK,CAAA,0BAAA,CAA2B,MAAO,CAAA,cAAA,CAAe,MAAM,CAAC,CAAA;AAAA,OACrE;AAAA,KACF,CAAA;AAEF,IAAA,OAAO,OAAQ,CAAA,GAAA,CAAI,YAAY,CAAA,CAAE,KAAK,6BAA6B,CAAA,CAAA;AAAA,GACrE;AAAA,EAEA,2BAAA,CACE,gBACA,UAC+B,EAAA;AAC/B,IAAA,MAAM,eAAe,KAAM,CAAA,IAAA,CAAK,UAAU,CAAE,CAAA,GAAA,CAAI,OAAM,EAAM,KAAA;AAC1D,MAAA,MAAM,CAAC,UAAY,EAAA,OAAO,CAAI,GAAA,MAAM,QAAQ,GAAI,CAAA;AAAA,QAC9C,IAAK,CAAA,aAAA;AAAA,UACH,cAAA;AAAA,UACA,gBAAA;AAAA,UACA,SAAA;AAAA,UACA,MAAA;AAAA,UACA,EAAA;AAAA,SACF;AAAA,QACA,KAAK,aAAc,CAAA,cAAA,EAAgB,EAAI,EAAA,IAAA,EAAM,QAAQ,EAAE,CAAA;AAAA,OACxD,CAAA,CAAA;AACD,MAAI,IAAA,UAAA,CAAW,EAAM,IAAA,OAAA,CAAQ,EAAI,EAAA;AAC/B,QAAO,OAAAC,kBAAA;AAAA,UACL;AAAA,YACE,uBAAA,EAAyB,MACvB,OAAA,CAAQ,IAAK,EAAA,CAAE,KAAK,CAAM,CAAA,MAAA,EAAE,IAAM,EAAA,CAAA,EAAI,CAAA,CAAA;AAAA,WAC1C;AAAA,UACA;AAAA,YACE,aAAA,EAAe,MAAM,UAAA,CAAW,IAAK,EAAA;AAAA,WACvC;AAAA,SACA,CAAA,IAAA;AAAA,UACA,CAAC,SAAuC,MAAA;AAAA,YACtC,IAAM,EAAA,WAAA;AAAA,YACN,SAAA;AAAA,WACF,CAAA;AAAA,SACF,CAAA;AAAA,OACF,MAAA,IAAW,WAAW,EAAI,EAAA;AACxB,QAAA,OAAO,IAAK,CAAA,0BAAA,CAA2B,cAAe,CAAA,IAAA,EAAM,OAAO,CAAA,CAAA;AAAA,OACrE;AACA,MAAA,OAAO,IAAK,CAAA,0BAAA,CAA2B,cAAe,CAAA,IAAA,EAAM,UAAU,CAAA,CAAA;AAAA,KACvE,CAAA,CAAA;AAED,IAAA,OAAO,OAAQ,CAAA,GAAA,CAAI,YAAY,CAAA,CAAE,KAAK,6BAA6B,CAAA,CAAA;AAAA,GACrE;AAAA,EAEA,MAAc,0BACZ,CAAA,WAAA,EACA,GAC+B,EAAA;AAC/B,IAAA,MAAM,YAAe,GAAA,IAAI,GAAI,CAAA,GAAA,CAAI,GAAG,CAAE,CAAA,QAAA,CAAA;AACtC,IAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,MACV,YACE,GAAI,CAAA,MAAA,CAAA,uBAAA,EACoB,+BAA+B,WAAuB,CAAA,SAAA,EAAA,MAAM,IAAI,IAAK,EAAA,CAAA,CAAA,CAAA;AAAA,KACjG,CAAA;AACA,IAAO,OAAA;AAAA,MACL,SAAA,EAAW,qBAAsB,CAAA,GAAA,CAAI,MAAM,CAAA;AAAA,MAC3C,YAAY,GAAI,CAAA,MAAA;AAAA,MAChB,YAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEQ,cACN,cACA,EAAA,KAAA,EACA,UACA,EAAA,MAAA,EACA,WACA,aACmB,EAAA;AACnB,IAAA,MAAM,MAAS,GAAA,CAAC,CAAc,KAAA,kBAAA,CAAmB,CAAC,CAAA,CAAA;AAClD,IAAI,IAAA,YAAA,GAAe,KACf,GAAA,CAAA,MAAA,EAAS,MAAO,CAAA,KAAK,CAAK,CAAA,CAAA,EAAA,MAAA,CAAO,UAAU,CAAA,CAAA,CAAA,GAC3C,CAAQ,KAAA,EAAA,MAAA,CAAO,UAAU,CAAA,CAAA,CAAA,CAAA;AAC7B,IAAA,IAAI,SAAW,EAAA;AACb,MAAgB,YAAA,IAAA,CAAA,YAAA,EAAe,OAAO,SAAS,CAAA,CAAA,CAAA,CAAA;AAAA,KACjD;AACA,IAAgB,YAAA,IAAA,CAAA,CAAA,EAAI,OAAO,MAAM,CAAA,CAAA,CAAA,CAAA;AAEjC,IAAI,IAAA,GAAA,CAAA;AACJ,IAAI,IAAA,WAAA,CAAA;AACJ,IAAA,IAAI,eAAe,mBAAqB,EAAA;AACtC,MAAA,CAAC,GAAK,EAAA,WAAW,CAAI,GAAA,IAAA,CAAK,4BAA4B,cAAc,CAAA,CAAA;AAAA,KAC3D,MAAA,IAAAC,sBAAA,CAAG,cAAe,CAAAC,iBAAA,CAAO,yBAAyB,CAAG,EAAA;AAC9D,MAAA,CAAC,GAAK,EAAA,WAAW,CAAI,GAAA,IAAA,CAAK,kBAAmB,EAAA,CAAA;AAAA,KACxC,MAAA;AACL,MAAA,OAAO,OAAQ,CAAA,MAAA;AAAA,QACb,IAAI,KAAA;AAAA,UACF,gCAAgC,cAAe,CAAA,IAAA,CAAA,+BAAA,CAAA;AAAA,SACjD;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAI,IAAA,GAAA,CAAI,aAAa,GAAK,EAAA;AACxB,MAAA,GAAA,CAAI,QAAW,GAAA,YAAA,CAAA;AAAA,KACV,MAAA;AACL,MAAA,GAAA,CAAI,QAAY,IAAA,YAAA,CAAA;AAAA,KAClB;AAEA,IAAA,IAAI,aAAe,EAAA;AACjB,MAAA,GAAA,CAAI,SAAS,CAAiB,cAAA,EAAA,aAAA,CAAA,CAAA,CAAA;AAAA,KAChC;AAEA,IAAO,OAAAC,yBAAA,CAAM,KAAK,WAAW,CAAA,CAAA;AAAA,GAC/B;AAAA,EAEQ,4BACN,cACoB,EAAA;AA5NxB,IAAA,IAAA,EAAA,CAAA;AA6NI,IAAA,MAAM,WAA2B,GAAA;AAAA,MAC/B,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,MAAQ,EAAA,kBAAA;AAAA,QACR,cAAgB,EAAA,kBAAA;AAAA,QAChB,aAAA,EAAe,UAAU,cAAe,CAAA,mBAAA,CAAA,CAAA;AAAA,OAC1C;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,GAAW,GAAA,IAAI,GAAI,CAAA,cAAA,CAAe,GAAG,CAAA,CAAA;AAC3C,IAAI,IAAA,GAAA,CAAI,aAAa,QAAU,EAAA;AAC7B,MAAY,WAAA,CAAA,KAAA,GAAQ,IAAIC,gBAAA,CAAM,KAAM,CAAA;AAAA,QAClC,EACE,EAAA,CAAA,EAAA,GAAAC,iCAAA;AAAA,UACE,cAAe,CAAA,MAAA;AAAA,UACf,cAAe,CAAA,MAAA;AAAA,cAFjB,IAGK,GAAA,EAAA,GAAA,KAAA,CAAA;AAAA,QACP,kBAAA,EAAoB,CAAC,cAAe,CAAA,aAAA;AAAA,OACrC,CAAA,CAAA;AAAA,KACH;AACA,IAAO,OAAA,CAAC,KAAK,WAAW,CAAA,CAAA;AAAA,GAC1B;AAAA,EACQ,kBAAyC,GAAA;AAC/C,IAAM,MAAA,EAAA,GAAK,IAAIC,qBAAW,EAAA,CAAA;AAC1B,IAAA,EAAA,CAAG,eAAgB,EAAA,CAAA;AAEnB,IAAM,MAAA,OAAA,GAAU,GAAG,iBAAkB,EAAA,CAAA;AACrC,IAAM,MAAA,IAAA,GAAO,GAAG,cAAe,EAAA,CAAA;AAE/B,IAAA,MAAM,QAAQL,sBAAG,CAAA,YAAA,CAAa,IAAK,CAAA,YAAA,CAAa,OAAO,SAAS,CAAA,CAAA;AAEhE,IAAA,MAAM,WAA2B,GAAA;AAAA,MAC/B,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,MAAQ,EAAA,kBAAA;AAAA,QACR,cAAgB,EAAA,kBAAA;AAAA,QAChB,eAAe,CAAU,OAAA,EAAA,KAAA,CAAA,CAAA;AAAA,OAC3B;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,GAAM,GAAA,IAAI,GAAI,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAClC,IAAI,IAAA,GAAA,CAAI,aAAa,QAAU,EAAA;AAC7B,MAAY,WAAA,CAAA,KAAA,GAAQ,IAAIG,gBAAA,CAAM,KAAM,CAAA;AAAA,QAClC,EAAI,EAAAH,sBAAA,CAAG,YAAa,CAAA,OAAA,CAAQ,MAAgB,CAAA;AAAA,OAC7C,CAAA,CAAA;AAAA,KACH;AACA,IAAO,OAAA,CAAC,KAAK,WAAW,CAAA,CAAA;AAAA,GAC1B;AACF;;AClOO,MAAM,yBAAoC,GAAA,+BAAA;AAO1C,MAAM,sBACX,GAAA,qCAAA;AAgBK,MAAM,eAAgB,CAAA;AAAA,EAG3B,WAAA,CACmB,QACA,eACjB,EAAA;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA,CAAA;AAJnB,IAAiB,IAAA,CAAA,wBAAA,uBAA+B,GAA4B,EAAA,CAAA;AAAA,GAKzE;AAAA,EAEI,qBACL,OACgB,EAAA;AAChB,IAAM,MAAA,EAAE,eAAkB,GAAA,OAAA,CAAA;AAC1B,IAAO,OAAA,OAAO,GAAK,EAAA,GAAA,EAAK,IAAS,KAAA;AAC/B,MAAA,MAAM,KAAQ,GAAAL,oDAAA;AAAA,QACZ,GAAA,CAAI,OAAO,eAAe,CAAA;AAAA,OAC5B,CAAA;AAEA,MAAM,MAAA,iBAAA,GAAA,CACJ,MAAM,aAAc,CAAA,SAAA;AAAA,QAClB,CAAC,EAAE,UAAY,EAAAW,gDAAA,EAA2B,CAAA;AAAA,QAC1C;AAAA,UACE,KAAA;AAAA,SACF;AAAA,SAEF,CAAC,CAAA,CAAA;AAEH,MAAI,IAAA,iBAAA,CAAkB,MAAW,KAAAC,sCAAA,CAAgB,IAAM,EAAA;AACrD,QAAI,GAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA,EAAE,OAAO,IAAIC,sBAAA,CAAgB,cAAc,CAAA,EAAG,CAAA,CAAA;AACnE,QAAA,OAAA;AAAA,OACF;AAEA,MAAA,MAAM,UAAa,GAAA,MAAM,IAAK,CAAA,aAAA,CAAc,GAAG,CAAA,CAAA;AAC/C,MAAW,UAAA,CAAA,GAAA,EAAK,KAAK,IAAI,CAAA,CAAA;AAAA,KAC3B,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAc,WAA+C,EAAA;AACzE,IAAA,MAAM,eAAkB,GAAA,MAAM,IAAK,CAAA,oBAAA,CAAqB,WAAW,CAAA,CAAA;AACnE,IAAA,IAAI,UAAa,GAAA,IAAA,CAAK,wBAAyB,CAAA,GAAA,CAAI,gBAAgB,IAAI,CAAA,CAAA;AACvE,IAAA,IAAI,CAAC,UAAY,EAAA;AAQf,MAAM,MAAA,MAAA,GAAS,KAAK,MAAO,CAAA,KAAA,CAAM,EAAE,OAAS,EAAA,eAAA,CAAgB,MAAM,CAAA,CAAA;AAClE,MAAA,UAAA,GAAaC,yCAAsB,CAAA;AAAA,QACjC,aAAa,MAAM,MAAA;AAAA,QACnB,MAAA,EAAQ,CAAC,eAAgB,CAAA,aAAA;AAAA,QACzB,MAAA,EAAQ,OAAM,GAAO,KAAA;AAzH7B,UAAA,IAAA,EAAA,CAAA;AA2HU,UAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,oBAAA,CAAqB,GAAG,CAAA,CAAA;AACnD,UAAA,MAAM,GAAM,GAAA,IAAI,GAAI,CAAA,OAAA,CAAQ,GAAG,CAAA,CAAA;AAC/B,UAAO,OAAA;AAAA,YACL,UAAU,GAAI,CAAA,QAAA;AAAA,YACd,MAAM,GAAI,CAAA,QAAA;AAAA,YACV,MAAM,GAAI,CAAA,IAAA;AAAA,YACV,KAAI,EAAuB,GAAAL,iCAAA,CAAA,EAAA,EAAI,OAAQ,CAAA,MAAM,MAAzC,IAA4C,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,QAAA,EAAA;AAAA,WAClD,CAAA;AAAA,SACF;AAAA,QACA,aAAa,EAAE,CAAC,IAAI,WAAY,CAAA,OAAA,CAAA,CAAS,GAAG,EAAG,EAAA;AAAA,QAC/C,OAAS,EAAA,CAAC,KAAO,EAAA,GAAA,EAAK,GAAQ,KAAA;AAC5B,UAAA,MAAM,eAAe,IAAIrB,qBAAA;AAAA,YACvB,YAAY,eAAgB,CAAA,IAAA,CAAA,eAAA,CAAA;AAAA,YAC5B,KAAA;AAAA,WACF,CAAA;AAEA,UAAA,MAAA,CAAO,MAAM,YAAY,CAAA,CAAA;AAEzB,UAAA,MAAM,IAA0B,GAAA;AAAA,YAC9B,KAAA,EAAO2B,sBAAe,YAAc,EAAA;AAAA,cAClC,YAAA,EAAc,OAAQ,CAAA,GAAA,CAAI,QAAa,KAAA,aAAA;AAAA,aACxC,CAAA;AAAA,YACD,SAAS,EAAE,MAAA,EAAQ,IAAI,MAAQ,EAAA,GAAA,EAAK,IAAI,WAAY,EAAA;AAAA,YACpD,QAAA,EAAU,EAAE,UAAA,EAAY,GAAI,EAAA;AAAA,WAC9B,CAAA;AAEA,UAAA,GAAA,CAAI,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,SAC3B;AAAA,QACA,UAAA,EAAY,CAAC,QAAA,EAAU,GAAQ,KAAA;AAvJvC,UAAA,IAAA,EAAA,CAAA;AAyJU,UAAA,MAAM,KAAQ,GAAA,CAAA,EAAA,GAAA,GAAA,CAAI,MAAO,CAAA,sBAAsB,MAAjC,IAAsC,GAAA,EAAA,GAAA,EAAA,CAAA;AACpD,UAAS,QAAA,CAAA,SAAA,CAAU,iBAAiB,KAAK,CAAA,CAAA;AAAA,SAC3C;AAAA,OACD,CAAA,CAAA;AAED,MAAA,IAAA,CAAK,wBAAyB,CAAA,GAAA,CAAI,eAAgB,CAAA,IAAA,EAAM,UAAU,CAAA,CAAA;AAAA,KACpE;AAEA,IAAO,OAAA,UAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAc,qBAAqB,GAAuC,EAAA;AACxE,IAAM,MAAA,WAAA,GAAc,GAAI,CAAA,MAAA,CAAO,yBAAyB,CAAA,CAAA;AACxD,IAAA,IAAI,CAAC,WAAa,EAAA;AAChB,MAAM,MAAA,IAAIjB,iBAAW,CAAA,CAAA,SAAA,EAAY,yBAAoC,CAAA,SAAA,CAAA,CAAA,CAAA;AAAA,KACvE;AAEA,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,eAAA,CACxB,aACA,CAAA,IAAA,CAAK,CAAY,QAAA,KAAA,QAAA,CAAS,IAAK,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,IAAA,KAAS,WAAW,CAAC,CAAA,CAAA;AAC9D,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAM,MAAA,IAAIkB,oBAAc,CAAA,CAAA,SAAA,EAAY,WAAwB,CAAA,WAAA,CAAA,CAAA,CAAA;AAAA,KAC9D;AAEA,IAAO,OAAA,OAAA,CAAA;AAAA,GACT;AACF;;ACvGO,MAAM,iBAAkB,CAAA;AAAA,EAc7B,YAA+B,GAA4B,EAAA;AAA5B,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA,CAAA;AAZ/B,IAAQ,IAAA,CAAA,6BAAA,GAA0CC,eAAS,UAAW,CAAA;AAAA,MACpE,OAAS,EAAA,EAAA;AAAA,KACV,CAAA,CAAA;AAAA,GAU2D;AAAA,EAJ5D,OAAO,cAAc,GAA4B,EAAA;AAC/C,IAAO,OAAA,IAAI,kBAAkB,GAAG,CAAA,CAAA;AAAA,GAClC;AAAA,EAIA,MAAa,KAAiC,GAAA;AAC5C,IAAM,MAAA,MAAA,GAAS,KAAK,GAAI,CAAA,MAAA,CAAA;AACxB,IAAM,MAAA,MAAA,GAAS,KAAK,GAAI,CAAA,MAAA,CAAA;AACxB,IAAM,MAAA,WAAA,GAAc,KAAK,GAAI,CAAA,WAAA,CAAA;AAE7B,IAAA,MAAA,CAAO,KAAK,iCAAiC,CAAA,CAAA;AAE7C,IAAA,IAAI,CAAC,MAAA,CAAO,GAAI,CAAA,YAAY,CAAG,EAAA;AAC7B,MAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,aAAe,EAAA;AAC1C,QAAM,MAAA,IAAI,MAAM,qCAAqC,CAAA,CAAA;AAAA,OACvD;AACA,MAAO,MAAA,CAAA,IAAA;AAAA,QACL,uEAAA;AAAA,OACF,CAAA;AACA,MAAO,OAAA;AAAA,QACL,QAAQC,0BAAO,EAAA;AAAA,OACjB,CAAA;AAAA,KACF;AACA,IAAM,MAAA,eAAA,GAAkB,KAAK,oBAAqB,EAAA,CAAA;AAElD,IAAM,MAAA,OAAA,GAAU,KAAK,UAAW,EAAA,CAAA;AAEhC,IAAM,MAAA,eAAA,GAAkB,KAAK,kBAAmB,EAAA,CAAA;AAEhD,IAAA,MAAM,KAAQ,GAAA,IAAA,CAAK,QAAS,CAAA,MAAA,EAAQ,eAAe,CAAA,CAAA;AAEnD,IAAM,MAAA,cAAA,GAAiB,KAAK,iBAAkB,EAAA,CAAA;AAE9C,IAAM,MAAA,eAAA,GAAkB,KAAK,kBAAmB,CAAA;AAAA,MAC9C,MAAA;AAAA,MACA,OAAA;AAAA,MACA,cAAA;AAAA,MACA,eAAA;AAAA,MACA,kBAAA,EAAoB,KAAK,qBAAsB,EAAA;AAAA,KAChD,CAAA,CAAA;AAED,IAAA,MAAM,SAAS,IAAK,CAAA,WAAA;AAAA,MAClB,eAAA;AAAA,MACA,eAAA;AAAA,MACA,KAAK,GAAI,CAAA,UAAA;AAAA,MACT,KAAA;AAAA,MACA,WAAA;AAAA,KACF,CAAA;AAEA,IAAO,OAAA;AAAA,MACL,eAAA;AAAA,MACA,eAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA;AAAA,MACA,eAAA;AAAA,MACA,MAAA;AAAA,MACA,cAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEO,mBAAmB,eAA8C,EAAA;AACtE,IAAA,IAAA,CAAK,eAAkB,GAAA,eAAA,CAAA;AACvB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,iCAAiC,eAA2B,EAAA;AACjE,IAAA,IAAA,CAAK,6BAAgC,GAAA,eAAA,CAAA;AACrC,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,mBAAmB,eAA6C,EAAA;AACrE,IAAA,IAAA,CAAK,eAAkB,GAAA,eAAA,CAAA;AACvB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,WAAW,OAA6B,EAAA;AAC7C,IAAA,IAAA,CAAK,OAAU,GAAA,OAAA,CAAA;AACf,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,kBAAkB,cAA2C,EAAA;AAClE,IAAA,IAAA,CAAK,cAAiB,GAAA,cAAA,CAAA;AACtB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,SAAS,KAAyB,EAAA;AACvC,IAAA,IAAA,CAAK,KAAQ,GAAA,KAAA,CAAA;AACb,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEU,oBAAuB,GAAA;AAjLnC,IAAA,IAAA,EAAA,CAAA;AAkLI,IAAM,MAAA,eAAA,GAAA,CAAA,CACJ,UAAK,GAAI,CAAA,MAAA,CAAO,uBAAuB,4BAA4B,CAAA,KAAnE,IAAwE,GAAA,EAAA,GAAA,EACxE,EAAA,GAAA;AAAA,MACA,CACG,CAAA,MAAA;AAAA,QACC,KAAA,EAAO,CAAE,CAAA,SAAA,CAAU,OAAO,CAAA;AAAA,QAC1B,UAAA,EAAY,CAAE,CAAA,SAAA,CAAU,YAAY,CAAA;AAAA,QACpC,MAAA,EAAQ,CAAE,CAAA,SAAA,CAAU,QAAQ,CAAA;AAAA,QAC5B,UAAY,EAAA,iBAAA;AAAA,OACd,CAAA;AAAA,KACJ,CAAA;AAEA,IAAA,IAAA,CAAK,IAAI,MAAO,CAAA,IAAA;AAAA,MACd,sDAAsD,eAAgB,CAAA,MAAA,CAAA,CAAA;AAAA,KACxE,CAAA;AACA,IAAO,OAAA,eAAA,CAAA;AAAA,GACT;AAAA,EAEU,qBACR,eAC4B,EAAA;AAC5B,IAAM,MAAA,MAAA,GAAS,KAAK,GAAI,CAAA,MAAA,CAAA;AACxB,IAAA,IAAA,CAAK,eAAkB,GAAA,0BAAA;AAAA,MACrB,MAAA;AAAA,MACA,KAAK,GAAI,CAAA,UAAA;AAAA,MACT,eAAA;AAAA,KACF,CAAA;AAEA,IAAA,OAAO,IAAK,CAAA,eAAA,CAAA;AAAA,GACd;AAAA,EAEU,qBACR,OAC2B,EAAA;AAC3B,IAAK,IAAA,CAAA,eAAA,GAAkB,IAAI,uBAAA,CAAwB,OAAO,CAAA,CAAA;AAC1D,IAAA,OAAO,IAAK,CAAA,eAAA,CAAA;AAAA,GACd;AAAA,EAEU,YAAkC,GAAA;AAC1C,IAAK,IAAA,CAAA,OAAA,GAAU,IAAI,4BAA6B,CAAA;AAAA,MAC9C,MAAA,EAAQ,KAAK,GAAI,CAAA,MAAA;AAAA,KAClB,CAAA,CAAA;AAED,IAAA,OAAO,IAAK,CAAA,OAAA,CAAA;AAAA,GACd;AAAA,EAEU,mBAAA,CACR,QACA,eAC0B,EAAA;AAC1B,IAAA,QAAQ,MAAQ;AAAA,MACd,KAAK,aAAA;AACH,QAAK,IAAA,CAAA,cAAA,GACH,IAAK,CAAA,8BAAA,CAA+B,eAAe,CAAA,CAAA;AACrD,QAAA,MAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAK,IAAA,CAAA,cAAA,GAAiB,IAAK,CAAA,uBAAA,CAAwB,eAAe,CAAA,CAAA;AAClE,QAAA,MAAA;AAAA,MACF;AACE,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAgD,6CAAA,EAAA,MAAA,CAAA,CAAA,CAAA;AAAA,SAClD,CAAA;AAAA,KACJ;AAEA,IAAA,OAAO,IAAK,CAAA,cAAA,CAAA;AAAA,GACd;AAAA,EAEU,+BACR,eAC0B,EAAA;AAC1B,IAAO,OAAA,IAAI,0BAA0B,eAAe,CAAA,CAAA;AAAA,GACtD;AAAA,EAEU,wBACR,gBAC0B,EAAA;AAC1B,IAAM,MAAA,IAAI,MAAM,iBAAiB,CAAA,CAAA;AAAA,GACnC;AAAA,EAEU,UAAA,CACR,QACA,eACiB,EAAA;AACjB,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAI,eAAgB,CAAA,MAAA,EAAQ,eAAe,CAAA,CAAA;AACxD,IAAA,OAAO,IAAK,CAAA,KAAA,CAAA;AAAA,GACd;AAAA,EAEU,WACR,CAAA,eAAA,EACA,eACA,EAAA,UAAA,EACA,OACA,aACgB,EAAA;AAChB,IAAM,MAAA,MAAA,GAAS,KAAK,GAAI,CAAA,MAAA,CAAA;AACxB,IAAA,MAAM,SAASA,0BAAO,EAAA,CAAA;AACtB,IAAA,MAAA,CAAO,IAAI,QAAU,EAAA,KAAA,CAAM,qBAAqB,EAAE,aAAA,EAAe,CAAC,CAAA,CAAA;AAClE,IAAO,MAAA,CAAA,GAAA,CAAIC,2BAAQ,CAAA,IAAA,EAAM,CAAA,CAAA;AACzB,IAAO,MAAA,CAAA,GAAA;AAAA,MACLC,sDAAkC,CAAA;AAAA,QAChC,WAAa,EAAAC,4CAAA;AAAA,OACd,CAAA;AAAA,KACH,CAAA;AAEA,IAAA,MAAA,CAAO,IAAK,CAAA,sBAAA,EAAwB,OAAO,GAAA,EAAK,GAAQ,KAAA;AACtD,MAAM,MAAA,SAAA,GAAY,IAAI,MAAO,CAAA,SAAA,CAAA;AAC7B,MAAA,MAAM,cAAsC,GAAI,CAAA,IAAA,CAAA;AAChD,MAAI,IAAA;AACF,QAAM,MAAA,QAAA,GAAW,MAAM,eAAA,CAAgB,4BAA6B,CAAA;AAAA,UAClE,QAAQ,WAAY,CAAA,MAAA;AAAA,UACpB,IAAA,EAAM,WAAY,CAAA,IAAA,IAAQ,EAAC;AAAA,SAC5B,CAAA,CAAA;AACD,QAAA,GAAA,CAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,eACV,CAAP,EAAA;AACA,QAAO,MAAA,CAAA,KAAA;AAAA,UACL,6CAA6C,SAAoB,CAAA,QAAA,EAAA,CAAA,CAAA,CAAA;AAAA,SACnE,CAAA;AACA,QAAI,GAAA,CAAA,MAAA,CAAO,GAAG,CAAE,CAAA,IAAA,CAAK,EAAE,KAAO,EAAA,CAAA,CAAE,SAAS,CAAA,CAAA;AAAA,OAC3C;AAAA,KACD,CAAA,CAAA;AAED,IAAA,MAAA,CAAO,GAAI,CAAA,WAAA,EAAa,OAAO,CAAA,EAAG,GAAQ,KAAA;AACxC,MAAA,MAAM,cAAiB,GAAA,MAAM,IAAK,CAAA,mBAAA,CAAoB,eAAe,CAAA,CAAA;AACrE,MAAA,GAAA,CAAI,IAAK,CAAA;AAAA,QACP,KAAA,EAAO,cAAe,CAAA,GAAA,CAAI,CAAO,EAAA,MAAA;AAAA,UAC/B,MAAM,EAAG,CAAA,IAAA;AAAA,UACT,cAAc,EAAG,CAAA,YAAA;AAAA,UACjB,cAAc,EAAG,CAAA,YAAA;AAAA,UACjB,mBAAmB,EAAG,CAAA,iBAAA;AAAA,SACtB,CAAA,CAAA;AAAA,OACH,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAED,IAA0B,yBAAA,CAAA,MAAA,EAAQ,YAAY,eAAe,CAAA,CAAA;AAE7D,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAgB,oBACd,eACA,EAAA;AACA,IAAM,MAAA,cAAA,GAAiB,MAAM,eAAA,CAAgB,WAAY,EAAA,CAAA;AAEzD,IAAA,IAAA,CAAK,IAAI,MAAO,CAAA,IAAA;AAAA,MACd,iDAAiD,cAAe,CAAA,MAAA,CAAA,CAAA;AAAA,KAClE,CAAA;AAEA,IAAO,OAAA,cAAA,CAAA;AAAA,GACT;AAAA,EAEU,uBAA0B,GAAA;AAClC,IAAO,OAAA,IAAA,CAAK,IAAI,MAAO,CAAA,SAAA;AAAA,MACrB,sCAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEU,UAAgC,GAAA;AA9U5C,IAAA,IAAA,EAAA,CAAA;AA+UI,IAAA,OAAA,CAAO,EAAK,GAAA,IAAA,CAAA,OAAA,KAAL,IAAgB,GAAA,EAAA,GAAA,IAAA,CAAK,YAAa,EAAA,CAAA;AAAA,GAC3C;AAAA,EAEU,kBAAqB,GAAA;AAlVjC,IAAA,IAAA,EAAA,CAAA;AAmVI,IAAA,OAAA,CACE,UAAK,eAAL,KAAA,IAAA,GAAA,EAAA,GACA,IAAK,CAAA,oBAAA,CAAqB,KAAK,6BAA6B,CAAA,CAAA;AAAA,GAEhE;AAAA,EAEU,iBAA8C,GAAA;AAzV1D,IAAA,IAAA,EAAA,CAAA;AA0VI,IACE,OAAA,CAAA,EAAA,GAAA,IAAA,CAAK,cAAL,KAAA,IAAA,GAAA,EAAA,GACA,IAAK,CAAA,mBAAA;AAAA,MACH,KAAK,uBAAwB,EAAA;AAAA,MAC7B,KAAK,kBAAmB,EAAA;AAAA,KAC1B,CAAA;AAAA,GAEJ;AAAA,EAEU,mBAAmB,OAA2C,EAAA;AAnW1E,IAAA,IAAA,EAAA,CAAA;AAoWI,IAAA,OAAA,CAAO,EAAK,GAAA,IAAA,CAAA,eAAA,KAAL,IAAwB,GAAA,EAAA,GAAA,IAAA,CAAK,qBAAqB,OAAO,CAAA,CAAA;AAAA,GAClE;AAAA,EAEU,qBAAwB,GAAA;AAChC,IAAM,MAAA,yBAAA,GAA4B,IAAK,CAAA,GAAA,CAAI,MAAO,CAAA,sBAAA;AAAA,MAChD,wBAAA;AAAA,KACF,CAAA;AAEA,IAAM,MAAA,mBAAA,GAAsB,IAAK,CAAA,GAAA,CAAI,MAAO,CAAA,iBAAA;AAAA,MAC1C,gCAAA;AAAA,KACF,CAAA;AAEA,IAAI,IAAA,kBAAA,CAAA;AAEJ,IAAA,IAAI,yBAA2B,EAAA;AAC7B,MAAA,kBAAA,GAAqB,eAAgB,CAAA,MAAA;AAAA,QAAO,CAC1C,GAAA,KAAA,yBAAA,CAA0B,QAAS,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,OACnD,CAAA;AAAA,KACF;AAEA,IAAA,IAAI,mBAAqB,EAAA;AACvB,MAAA,kBAAA,GAAqB,kBAAsB,IAAA,IAAA,GAAA,kBAAA,GAAA,eAAA,CAAA;AAE3C,MAAA,KAAA,MAAW,OAAO,kBAAoB,EAAA;AACpC,QAAA,IAAI,mBAAoB,CAAA,GAAA,CAAI,GAAI,CAAA,UAAU,CAAG,EAAA;AAC3C,UAAA,GAAA,CAAI,UAAa,GAAA,mBAAA,CAAoB,SAAU,CAAA,GAAA,CAAI,UAAU,CAAA,CAAA;AAAA,SAC/D;AAAA,OACF;AAAA,KACF;AAEA,IAAO,OAAA,kBAAA,CAAA;AAAA,GACT;AAAA,EAEU,QAAA,CACR,QACA,eACA,EAAA;AAxYJ,IAAA,IAAA,EAAA,CAAA;AAyYI,IAAA,OAAA,CAAO,UAAK,KAAL,KAAA,IAAA,GAAA,EAAA,GAAc,IAAK,CAAA,UAAA,CAAW,QAAQ,eAAe,CAAA,CAAA;AAAA,GAC9D;AACF;;ACtVA,eAAsB,aACpB,OACyB,EAAA;AACzB,EAAA,MAAM,EAAE,MAAA,EAAW,GAAA,MAAM,iBAAkB,CAAA,aAAA,CAAc,OAAO,CAAA,CAC7D,kBAAmB,CAAA,OAAA,CAAQ,eAAe,CAAA,CAC1C,KAAM,EAAA,CAAA;AACT,EAAO,OAAA,MAAA,CAAA;AACT;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/CatalogClusterLocator.ts","../src/cluster-locator/LocalKubectlProxyLocator.ts","../src/cluster-locator/index.ts","../src/routes/resourcesRoutes.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesProxy.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\n/**\n *\n * @public\n */\nexport type SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\n/**\n *\n * @public\n */\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n const awsCreds = await this.awsGetCredentials();\n\n if (!(awsCreds instanceof Credentials))\n throw new Error('No AWS credentials found.');\n\n let creds: SigningCreds = {\n accessKeyId: awsCreds.accessKeyId,\n secretAccessKey: awsCreds.secretAccessKey,\n sessionToken: awsCreds.sessionToken,\n };\n\n if (!this.validCredentials(creds))\n throw new Error('Invalid AWS credentials found.');\n if (!assumeRole) return creds;\n\n try {\n const params: AWS.STS.Types.AssumeRoleRequest = {\n RoleArn: assumeRole,\n RoleSessionName: 'backstage-login',\n };\n if (externalId) params.ExternalId = externalId;\n\n const assumedRole = await new AWS.STS().assumeRole(params).promise();\n\n if (!assumedRole.Credentials) {\n throw new Error(`No credentials returned for role ${assumeRole}`);\n }\n\n creds = {\n accessKeyId: assumedRole.Credentials.AccessKeyId,\n secretAccessKey: assumedRole.Credentials.SecretAccessKey,\n sessionToken: assumedRole.Credentials.SessionToken,\n };\n } catch (e) {\n console.warn(`There was an error assuming the role: ${e}`);\n throw new Error(`Unable to assume role: ${e}`);\n }\n return creds;\n }\n async getBearerToken(\n clusterName: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const credentials = await this.getCredentials(assumeRole, externalId);\n\n const request = {\n host: `sts.amazonaws.com`,\n path: `/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Expires=60`,\n headers: {\n 'x-k8s-aws-id': clusterName,\n },\n signQuery: true,\n };\n\n const signed = sign(request, credentials);\n const url = `https://${signed.host}${signed.path}`;\n const base64Url = Buffer.from(url, 'binary').toString('base64');\n const urlSafeBase64Url = base64Url\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return `k8s-aws-v1.${urlSafeBase64Url}`;\n }\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AWSClusterDetails,\n ): Promise<AWSClusterDetails> {\n const clusterDetailsWithAuthToken: AWSClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getBearerToken(\n clusterDetails.name,\n clusterDetails.assumeRole,\n clusterDetails.externalId,\n );\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\n/**\n *\n * @public\n */\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = authConfig.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\n/**\n *\n * @public\n */\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport type DispatchingKubernetesAuthTranslatorOptions = {\n authTranslatorMap: {\n [key: string]: KubernetesAuthTranslator;\n };\n};\n/**\n * used to direct a KubernetesAuthProvider to its corresponding KubernetesAuthTranslator\n * @public\n */\nexport class DispatchingKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private readonly translatorMap: { [key: string]: KubernetesAuthTranslator };\n\n constructor(options: DispatchingKubernetesAuthTranslatorOptions) {\n this.translatorMap = options.authTranslatorMap;\n }\n\n public decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n auth: KubernetesRequestAuth,\n ) {\n if (this.translatorMap[clusterDetails.authProvider]) {\n return this.translatorMap[\n clusterDetails.authProvider\n ].decorateClusterDetailsWithAuth(clusterDetails, auth);\n }\n throw new Error(\n `authProvider \"${clusterDetails.authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\n\n/**\n *\n * @public\n */\nexport class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined = authConfig.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n caFile: c.getOptionalString('caFile'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\n );\n }\n }\n}\n","/*\n * Copyright 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 */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { CATALOG_FILTER_EXISTS, CatalogApi } from '@backstage/catalog-client';\nimport {\n ANNOTATION_KUBERNETES_API_SERVER,\n ANNOTATION_KUBERNETES_API_SERVER_CA,\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP,\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY,\n ANNOTATION_KUBERNETES_DASHBOARD_URL,\n ANNOTATION_KUBERNETES_DASHBOARD_APP,\n} from '@backstage/plugin-kubernetes-common';\n\nexport class CatalogClusterLocator implements KubernetesClustersSupplier {\n private catalogClient: CatalogApi;\n\n constructor(catalogClient: CatalogApi) {\n this.catalogClient = catalogClient;\n }\n\n static fromConfig(catalogApi: CatalogApi): CatalogClusterLocator {\n return new CatalogClusterLocator(catalogApi);\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n const apiServerKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER}`;\n const apiServerCaKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER_CA}`;\n const authProviderKey = `metadata.annotations.${ANNOTATION_KUBERNETES_AUTH_PROVIDER}`;\n\n const filter: Record<string, symbol | string> = {\n kind: 'Resource',\n 'spec.type': 'kubernetes-cluster',\n [apiServerKey]: CATALOG_FILTER_EXISTS,\n [apiServerCaKey]: CATALOG_FILTER_EXISTS,\n [authProviderKey]: CATALOG_FILTER_EXISTS,\n };\n\n const clusters = await this.catalogClient.getEntities({\n filter: [filter],\n });\n return clusters.items.map(entity => {\n const clusterDetails: ClusterDetails = {\n name: entity.metadata.name,\n url: entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER]!,\n caData:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER_CA]!,\n authProvider:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_AUTH_PROVIDER]!,\n oidcTokenProvider:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER\n ]!,\n skipMetricsLookup:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP\n ]! === 'true'\n ? true\n : false,\n skipTLSVerify:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY\n ]! === 'true'\n ? true\n : false,\n dashboardUrl:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_URL]!,\n dashboardApp:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_APP]!,\n };\n\n return clusterDetails;\n });\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class LocalKubectlProxyClusterLocator\n implements KubernetesClustersSupplier\n{\n private readonly clusterDetails: ClusterDetails[];\n\n public constructor() {\n this.clusterDetails = [\n {\n name: 'local',\n url: 'http:/localhost:8001',\n authProvider: 'localKubectlProxy',\n skipMetricsLookup: true,\n },\n ];\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\nimport { CatalogClusterLocator } from './CatalogClusterLocator';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { LocalKubectlProxyClusterLocator } from './LocalKubectlProxyLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n catalogClient: CatalogApi,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'catalog':\n return CatalogClusterLocator.fromConfig(catalogClient);\n case 'localKubectlProxy':\n return new LocalKubectlProxyClusterLocator();\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\n};\n","/*\n * Copyright 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, AuthenticationError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '../types/types';\nimport { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalogApi: CatalogApi,\n objectsProvider: KubernetesObjectsProvider,\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 = getBearerTokenFromAuthorizationHeader(\n req.headers.authorization,\n );\n\n if (!token) {\n throw new AuthenticationError('No Backstage token');\n }\n\n const entity = await catalogApi.getEntityByRef(entityRef, {\n token: token,\n });\n\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity,\n auth: req.body.auth,\n });\n res.json(response);\n });\n\n router.post('/resources/custom/query', async (req, res) => {\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 entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n });\n res.json(response);\n });\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n ServiceLocatorRequestContext,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n getClustersByEntity(\n _entity: Entity,\n _requestContext: ServiceLocatorRequestContext,\n ): Promise<{ clusters: ClusterDetails[] }> {\n return this.clusterSupplier.getClusters().then(clusters => ({ clusters }));\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n CustomResource,\n CustomResourcesByEntity,\n KubernetesObjectsByEntity,\n ServiceLocatorRequestContext,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n KubernetesRequestAuth,\n CustomResourceMatcher,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\nconst isRejected = (\n input: PromiseSettledResult<unknown>,\n): input is PromiseRejectedResult => input.status === 'rejected';\n\nconst isFulfilled = <T>(\n input: PromiseSettledResult<T>,\n): input is PromiseFulfilledResult<T> => input.status === 'fulfilled';\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: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'daemonsets',\n objectType: 'daemonsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {\n authTranslator: KubernetesAuthTranslator;\n}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: 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 {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslator: KubernetesAuthTranslator;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n authTranslator,\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.authTranslator = authTranslator;\n }\n\n async getCustomResourcesByEntity({\n entity,\n auth,\n customResources,\n }: CustomResourcesByEntity): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity({\n entity,\n auth,\n }: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(entity, auth, this.objectTypesToFetch);\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n objectTypesToFetch: Set<ObjectToFetch>,\n customResources?: CustomResourceMatcher[],\n ) {\n const entityName =\n entity.metadata?.annotations?.['backstage.io/kubernetes-id'] ||\n entity.metadata?.name;\n\n const clusterDetailsDecoratedForAuth: ClusterDetails[] =\n await this.decorateClusterDetailsWithAuth(entity, auth, {\n objectTypesToFetch: objectTypesToFetch,\n customResources: customResources ?? [],\n });\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: objectTypesToFetch,\n labelSelector,\n customResources: (\n customResources ||\n clusterDetailsItem.customResources ||\n this.customResources\n ).map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\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(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n private async decorateClusterDetailsWithAuth(\n entity: Entity,\n auth: KubernetesRequestAuth,\n requestContext: ServiceLocatorRequestContext,\n ) {\n const clusterDetails: ClusterDetails[] = (\n await this.serviceLocator.getClustersByEntity(entity, requestContext)\n ).clusters;\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n const promiseResults = await Promise.allSettled(\n clusterDetails.map(cd => {\n return this.authTranslator.decorateClusterDetailsWithAuth(cd, auth);\n }),\n );\n\n promiseResults.filter(isRejected).map(item => {\n this.logger.info(`Failed to decorate cluster details: ${item.reason}`);\n });\n return promiseResults.filter(isFulfilled).map(item => item.value);\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources?.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n if (namespaces.size === 0) {\n return [result, []];\n }\n\n const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces(\n clusterDetails,\n namespaces,\n );\n\n result.errors.push(...podMetrics.errors);\n return [result, podMetrics.responses as PodStatusFetchResponse[]];\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Config,\n Cluster,\n CoreV1Api,\n KubeConfig,\n Metrics,\n User,\n bufferFromFileOrString,\n topPods,\n} from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n ObjectFetchParams,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\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';\n\nexport interface KubernetesClientBasedFetcherOptions {\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 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: Logger;\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 group,\n apiVersion,\n plural,\n params.namespace,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n ).then(\n (r: Response): Promise<FetchResult> =>\n r.ok\n ? r.json().then(\n ({ items }): FetchResponse => ({\n type: objectType,\n resources: items,\n }),\n )\n : this.handleUnsuccessfulResponse(params.clusterDetails.name, r),\n ),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespaces(\n clusterDetails: ClusterDetails,\n namespaces: Set<string>,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(namespaces).map(async ns => {\n const [podMetrics, podList] = await Promise.all([\n this.fetchResource(\n clusterDetails,\n 'metrics.k8s.io',\n 'v1beta1',\n 'pods',\n ns,\n ),\n this.fetchResource(clusterDetails, '', 'v1', 'pods', ns),\n ]);\n if (podMetrics.ok && podList.ok) {\n return topPods(\n {\n listPodForAllNamespaces: () =>\n podList.json().then(b => ({ body: b })),\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 fetchResource(\n clusterDetails: ClusterDetails,\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 if (\n clusterDetails.serviceAccountToken ||\n clusterDetails.authProvider === 'localKubectlProxy'\n ) {\n [url, requestInit] = this.fetchArgsFromClusterDetails(clusterDetails);\n } else if (fs.pathExistsSync(Config.SERVICEACCOUNT_TOKEN_PATH)) {\n [url, requestInit] = this.fetchArgsInCluster();\n } else {\n return Promise.reject(\n new Error(\n `no bearer token 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=${labelSelector}`;\n }\n\n return fetch(url, requestInit);\n }\n\n private fetchArgsFromClusterDetails(\n clusterDetails: ClusterDetails,\n ): [URL, RequestInit] {\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${clusterDetails.serviceAccountToken}`,\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 });\n }\n return [url, requestInit];\n }\n private fetchArgsInCluster(): [URL, RequestInit] {\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 const user = kc.getCurrentUser() as User;\n\n const token = fs.readFileSync(user.authProvider.config.tokenFile);\n\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n };\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","/*\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 */\n\nimport {\n ErrorResponseBody,\n ForwardedError,\n InputError,\n NotAllowedError,\n NotFoundError,\n serializeError,\n} from '@backstage/errors';\nimport { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';\nimport { kubernetesProxyPermission } from '@backstage/plugin-kubernetes-common';\nimport {\n PermissionEvaluator,\n AuthorizeResult,\n} from '@backstage/plugin-permission-common';\nimport { bufferFromFileOrString } from '@kubernetes/client-node';\nimport type { Request, RequestHandler } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport const APPLICATION_JSON: string = 'application/json';\n\n/**\n * The header that is used to specify the cluster name.\n *\n * @public\n */\nexport const HEADER_KUBERNETES_CLUSTER: string = 'Backstage-Kubernetes-Cluster';\n\n/**\n * The header that is used to specify the Authentication Authorities token.\n * e.x if using the google auth provider as your authentication authority then this field would be the google provided bearer token.\n * @public\n */\nexport const HEADER_KUBERNETES_AUTH: string =\n 'Backstage-Kubernetes-Authorization';\n\n/**\n * The options object expected to be passed as a parameter to KubernetesProxy.createRequestHandler().\n *\n * @public\n */\nexport type KubernetesProxyCreateRequestHandlerOptions = {\n permissionApi: PermissionEvaluator;\n};\n\n/**\n * Options accepted as a parameter by the KubernetesProxy\n *\n * @public\n */\nexport type KubernetesProxyOptions = {\n logger: Logger;\n clusterSupplier: KubernetesClustersSupplier;\n authTranslator: KubernetesAuthTranslator;\n};\n\n/**\n * A proxy that routes requests to the Kubernetes API.\n *\n * @public\n */\nexport class KubernetesProxy {\n private readonly middlewareForClusterName = new Map<string, RequestHandler>();\n private readonly logger: Logger;\n private readonly clusterSupplier: KubernetesClustersSupplier;\n private readonly authTranslator: KubernetesAuthTranslator;\n\n constructor(options: KubernetesProxyOptions) {\n this.logger = options.logger;\n this.clusterSupplier = options.clusterSupplier;\n this.authTranslator = options.authTranslator;\n }\n\n public createRequestHandler(\n options: KubernetesProxyCreateRequestHandlerOptions,\n ): RequestHandler {\n const { permissionApi } = options;\n return async (req, res, next) => {\n const token = getBearerTokenFromAuthorizationHeader(\n req.header('authorization'),\n );\n\n const authorizeResponse = (\n await permissionApi.authorize(\n [{ permission: kubernetesProxyPermission }],\n {\n token,\n },\n )\n )[0];\n\n if (authorizeResponse.result === AuthorizeResult.DENY) {\n res.status(403).json({ error: new NotAllowedError('Unauthorized') });\n return;\n }\n\n const cluster = await this.getClusterForRequest(req).then(cd =>\n this.authTranslator.decorateClusterDetailsWithAuth(cd, {}),\n );\n if (!req.headers.authorization) {\n req.headers.authorization = `Bearer ${cluster.serviceAccountToken}`;\n }\n const middleware = await this.getMiddleware(req);\n middleware(req, res, next);\n };\n }\n\n // We create one middleware per remote cluster and hold on to them, because\n // the secure property isn't possible to decide on a per-request basis with a\n // single middleware instance - and we don't expect it to change over time.\n private async getMiddleware(originalReq: Request): Promise<RequestHandler> {\n const originalCluster = await this.getClusterForRequest(originalReq);\n let middleware = this.middlewareForClusterName.get(originalCluster.name);\n if (!middleware) {\n const logger = this.logger.child({ cluster: originalCluster.name });\n middleware = createProxyMiddleware({\n logProvider: () => logger,\n secure: !originalCluster.skipTLSVerify,\n router: async req => {\n // Re-evaluate the cluster on each request, in case it has changed\n const cluster = await this.getClusterForRequest(req);\n const url = new URL(cluster.url);\n return {\n protocol: url.protocol,\n host: url.hostname,\n port: url.port,\n ca: bufferFromFileOrString('', cluster.caData)?.toString(),\n };\n },\n pathRewrite: { [`^${originalReq.baseUrl}`]: '' },\n onError: (error, req, res) => {\n const wrappedError = new ForwardedError(\n `Cluster '${originalCluster.name}' request error`,\n error,\n );\n\n logger.error(wrappedError);\n\n const body: ErrorResponseBody = {\n error: serializeError(wrappedError, {\n includeStack: process.env.NODE_ENV === 'development',\n }),\n request: { method: req.method, url: req.originalUrl },\n response: { statusCode: 500 },\n };\n res.status(500).json(body);\n },\n onProxyReq: (proxyReq, req) => {\n // the kubernetes proxy endpoint expects a header field labeled `Backstage-Kubernetes-Authorization` that will be used to authenticate with the Kubernetes Api. The token provided as a value should be an bearer token for the target cluster.\n if (req.header(HEADER_KUBERNETES_AUTH)) {\n const token = req.header(HEADER_KUBERNETES_AUTH) ?? '';\n proxyReq.setHeader('Authorization', token);\n }\n },\n });\n this.middlewareForClusterName.set(originalCluster.name, middleware);\n }\n return middleware;\n }\n\n private async getClusterForRequest(req: Request): Promise<ClusterDetails> {\n const clusterName = req.header(HEADER_KUBERNETES_CLUSTER);\n if (!clusterName) {\n throw new InputError(`Missing '${HEADER_KUBERNETES_CLUSTER}' header.`);\n }\n\n const cluster = await this.clusterSupplier\n .getClusters()\n .then(clusters => clusters.find(c => c.name === clusterName));\n if (!cluster) {\n throw new NotFoundError(`Cluster '${clusterName}' not found`);\n }\n\n return cluster;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { Config } from '@backstage/config';\nimport { kubernetesPermissions } from '@backstage/plugin-kubernetes-common';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Duration } from 'luxon';\nimport { Logger } from 'winston';\n\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport {\n KubernetesAuthTranslator,\n DispatchingKubernetesAuthTranslator,\n GoogleKubernetesAuthTranslator,\n NoopKubernetesAuthTranslator,\n AwsIamKubernetesAuthTranslator,\n GoogleServiceAccountAuthTranslator,\n AzureIdentityKubernetesAuthTranslator,\n OidcKubernetesAuthTranslator,\n} from '../kubernetes-auth-translator';\n\nimport { addResourceRoutesToRouter } from '../routes/resourcesRoutes';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n CustomResource,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesObjectsProvider,\n KubernetesObjectsProviderOptions,\n KubernetesObjectTypes,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n ServiceLocatorMethod,\n} from '../types/types';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\nimport { KubernetesProxy } from './KubernetesProxy';\n\n/**\n *\n * @public\n */\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n permissions: PermissionEvaluator;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @public\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n proxy: KubernetesProxy;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n authTranslatorMap: { [key: string]: KubernetesAuthTranslator };\n}>;\n\n/**\n *\n * @public\n */\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n private proxy?: KubernetesProxy;\n private authTranslatorMap?: { [key: string]: KubernetesAuthTranslator };\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n const permissions = this.env.permissions;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.getFetcher();\n\n const clusterSupplier = this.getClusterSupplier();\n\n const authTranslatorMap = this.getAuthTranslatorMap();\n\n const proxy = this.getProxy(logger, clusterSupplier);\n\n const serviceLocator = this.getServiceLocator();\n\n const objectsProvider = this.getObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(\n objectsProvider,\n clusterSupplier,\n this.env.catalogApi,\n proxy,\n permissions,\n );\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n proxy,\n objectsProvider,\n router,\n serviceLocator,\n authTranslatorMap,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n public setProxy(proxy?: KubernetesProxy) {\n this.proxy = proxy;\n return this;\n }\n\n public setAuthTranslatorMap(authTranslatorMap: {\n [key: string]: KubernetesAuthTranslator;\n }) {\n this.authTranslatorMap = authTranslatorMap;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n this.clusterSupplier = getCombinedClusterSupplier(\n config,\n this.env.catalogApi,\n refreshInterval,\n );\n\n return this.clusterSupplier;\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n const authTranslatorMap = this.getAuthTranslatorMap();\n this.objectsProvider = new KubernetesFanOutHandler({\n ...options,\n authTranslator: new DispatchingKubernetesAuthTranslator({\n authTranslatorMap,\n }),\n });\n\n return this.objectsProvider;\n }\n\n protected buildFetcher(): KubernetesFetcher {\n this.fetcher = new KubernetesClientBasedFetcher({\n logger: this.env.logger,\n });\n\n return this.fetcher;\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n this.serviceLocator =\n this.buildMultiTenantServiceLocator(clusterSupplier);\n break;\n case 'http':\n this.serviceLocator = this.buildHttpServiceLocator(clusterSupplier);\n break;\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n\n return this.serviceLocator;\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesProxy {\n const authTranslatorMap = this.getAuthTranslatorMap();\n const authTranslator = new DispatchingKubernetesAuthTranslator({\n authTranslatorMap,\n });\n this.proxy = new KubernetesProxy({\n logger,\n clusterSupplier,\n authTranslator,\n });\n return this.proxy;\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n catalogApi: CatalogApi,\n proxy: KubernetesProxy,\n permissionApi: PermissionEvaluator,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use('/proxy', proxy.createRequestHandler({ permissionApi }));\n router.use(express.json());\n router.use(\n createPermissionIntegrationRouter({\n permissions: kubernetesPermissions,\n }),\n );\n // @deprecated\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity: requestBody.entity,\n auth: requestBody.auth || {},\n });\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n\n addResourceRoutesToRouter(router, catalogApi, objectsProvider);\n\n return router;\n }\n\n protected buildAuthTranslatorMap() {\n this.authTranslatorMap = {\n google: new GoogleKubernetesAuthTranslator(),\n aws: new AwsIamKubernetesAuthTranslator(),\n azure: new AzureIdentityKubernetesAuthTranslator(this.env.logger),\n serviceAccount: new NoopKubernetesAuthTranslator(),\n googleServiceAccount: new GoogleServiceAccountAuthTranslator(),\n oidc: new OidcKubernetesAuthTranslator(),\n localKubectlProxy: new NoopKubernetesAuthTranslator(),\n };\n return this.authTranslatorMap;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getFetcher(): KubernetesFetcher {\n return this.fetcher ?? this.buildFetcher();\n }\n\n protected getClusterSupplier() {\n return (\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval)\n );\n }\n\n protected getServiceLocator(): KubernetesServiceLocator {\n return (\n this.serviceLocator ??\n this.buildServiceLocator(\n this.getServiceLocatorMethod(),\n this.getClusterSupplier(),\n )\n );\n }\n\n protected getObjectsProvider(options: KubernetesObjectsProviderOptions) {\n return this.objectsProvider ?? this.buildObjectsProvider(options);\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\n }\n\n protected getProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n return this.proxy ?? this.buildProxy(logger, clusterSupplier);\n }\n\n protected getAuthTranslatorMap() {\n return this.authTranslatorMap ?? this.buildAuthTranslatorMap();\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\nimport { PluginEndpointDiscovery } from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\n\n/**\n *\n * @public\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n clusterSupplier?: KubernetesClustersSupplier;\n discovery: PluginEndpointDiscovery;\n permissions: PermissionEvaluator;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["AWS","Credentials","sign","DefaultAzureCredential","container","_a","ForwardedError","ANNOTATION_KUBERNETES_API_SERVER","ANNOTATION_KUBERNETES_API_SERVER_CA","ANNOTATION_KUBERNETES_AUTH_PROVIDER","CATALOG_FILTER_EXISTS","ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER","ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP","ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY","ANNOTATION_KUBERNETES_DASHBOARD_URL","ANNOTATION_KUBERNETES_DASHBOARD_APP","InputError","parseEntityRef","getBearerTokenFromAuthorizationHeader","AuthenticationError","stringifyEntityRef","lodash","topPods","fs","Config","fetch","https","bufferFromFileOrString","KubeConfig","kubernetesProxyPermission","AuthorizeResult","NotAllowedError","createProxyMiddleware","serializeError","NotFoundError","Duration","Router","express","createPermissionIntegrationRouter","kubernetesPermissions"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -61,7 +61,7 @@ interface CustomResource extends ObjectToFetch {
|
|
|
61
61
|
*
|
|
62
62
|
* @public
|
|
63
63
|
*/
|
|
64
|
-
|
|
64
|
+
type KubernetesObjectTypes = 'pods' | 'services' | 'configmaps' | 'deployments' | 'limitranges' | 'replicasets' | 'horizontalpodautoscalers' | 'jobs' | 'cronjobs' | 'ingresses' | 'customresources' | 'statefulsets' | 'daemonsets';
|
|
65
65
|
/**
|
|
66
66
|
* Used to load cluster details from different sources
|
|
67
67
|
* @public
|
|
@@ -95,7 +95,7 @@ interface KubernetesServiceLocator {
|
|
|
95
95
|
*
|
|
96
96
|
* @public
|
|
97
97
|
*/
|
|
98
|
-
|
|
98
|
+
type ServiceLocatorMethod = 'multiTenant' | 'http';
|
|
99
99
|
/**
|
|
100
100
|
*
|
|
101
101
|
* @public
|
|
@@ -199,7 +199,7 @@ interface KubernetesObjectsProviderOptions {
|
|
|
199
199
|
*
|
|
200
200
|
* @public
|
|
201
201
|
*/
|
|
202
|
-
|
|
202
|
+
type ObjectsByEntityRequest = KubernetesRequestBody;
|
|
203
203
|
/**
|
|
204
204
|
*
|
|
205
205
|
* @public
|
|
@@ -236,7 +236,7 @@ interface KubernetesAuthTranslator {
|
|
|
236
236
|
*
|
|
237
237
|
* @public
|
|
238
238
|
*/
|
|
239
|
-
|
|
239
|
+
type SigningCreds = {
|
|
240
240
|
accessKeyId: string | undefined;
|
|
241
241
|
secretAccessKey: string | undefined;
|
|
242
242
|
sessionToken: string | undefined;
|
|
@@ -290,10 +290,19 @@ declare class GoogleServiceAccountAuthTranslator implements KubernetesAuthTransl
|
|
|
290
290
|
*
|
|
291
291
|
* @public
|
|
292
292
|
*/
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
293
|
+
type DispatchingKubernetesAuthTranslatorOptions = {
|
|
294
|
+
authTranslatorMap: {
|
|
295
|
+
[key: string]: KubernetesAuthTranslator;
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* used to direct a KubernetesAuthProvider to its corresponding KubernetesAuthTranslator
|
|
300
|
+
* @public
|
|
301
|
+
*/
|
|
302
|
+
declare class DispatchingKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
303
|
+
private readonly translatorMap;
|
|
304
|
+
constructor(options: DispatchingKubernetesAuthTranslatorOptions);
|
|
305
|
+
decorateClusterDetailsWithAuth(clusterDetails: ClusterDetails, auth: KubernetesRequestAuth): Promise<ClusterDetails>;
|
|
297
306
|
}
|
|
298
307
|
|
|
299
308
|
/**
|
|
@@ -329,19 +338,30 @@ declare const HEADER_KUBERNETES_AUTH: string;
|
|
|
329
338
|
*
|
|
330
339
|
* @public
|
|
331
340
|
*/
|
|
332
|
-
|
|
341
|
+
type KubernetesProxyCreateRequestHandlerOptions = {
|
|
333
342
|
permissionApi: PermissionEvaluator;
|
|
334
343
|
};
|
|
344
|
+
/**
|
|
345
|
+
* Options accepted as a parameter by the KubernetesProxy
|
|
346
|
+
*
|
|
347
|
+
* @public
|
|
348
|
+
*/
|
|
349
|
+
type KubernetesProxyOptions = {
|
|
350
|
+
logger: Logger;
|
|
351
|
+
clusterSupplier: KubernetesClustersSupplier;
|
|
352
|
+
authTranslator: KubernetesAuthTranslator;
|
|
353
|
+
};
|
|
335
354
|
/**
|
|
336
355
|
* A proxy that routes requests to the Kubernetes API.
|
|
337
356
|
*
|
|
338
357
|
* @public
|
|
339
358
|
*/
|
|
340
359
|
declare class KubernetesProxy {
|
|
360
|
+
private readonly middlewareForClusterName;
|
|
341
361
|
private readonly logger;
|
|
342
362
|
private readonly clusterSupplier;
|
|
343
|
-
private readonly
|
|
344
|
-
constructor(
|
|
363
|
+
private readonly authTranslator;
|
|
364
|
+
constructor(options: KubernetesProxyOptions);
|
|
345
365
|
createRequestHandler(options: KubernetesProxyCreateRequestHandlerOptions): RequestHandler;
|
|
346
366
|
private getMiddleware;
|
|
347
367
|
private getClusterForRequest;
|
|
@@ -362,7 +382,7 @@ interface KubernetesEnvironment {
|
|
|
362
382
|
*
|
|
363
383
|
* @public
|
|
364
384
|
*/
|
|
365
|
-
|
|
385
|
+
type KubernetesBuilderReturn = Promise<{
|
|
366
386
|
router: express.Router;
|
|
367
387
|
clusterSupplier: KubernetesClustersSupplier;
|
|
368
388
|
customResources: CustomResource[];
|
|
@@ -370,6 +390,9 @@ declare type KubernetesBuilderReturn = Promise<{
|
|
|
370
390
|
proxy: KubernetesProxy;
|
|
371
391
|
objectsProvider: KubernetesObjectsProvider;
|
|
372
392
|
serviceLocator: KubernetesServiceLocator;
|
|
393
|
+
authTranslatorMap: {
|
|
394
|
+
[key: string]: KubernetesAuthTranslator;
|
|
395
|
+
};
|
|
373
396
|
}>;
|
|
374
397
|
/**
|
|
375
398
|
*
|
|
@@ -383,6 +406,7 @@ declare class KubernetesBuilder {
|
|
|
383
406
|
private fetcher?;
|
|
384
407
|
private serviceLocator?;
|
|
385
408
|
private proxy?;
|
|
409
|
+
private authTranslatorMap?;
|
|
386
410
|
static createBuilder(env: KubernetesEnvironment): KubernetesBuilder;
|
|
387
411
|
constructor(env: KubernetesEnvironment);
|
|
388
412
|
build(): KubernetesBuilderReturn;
|
|
@@ -392,6 +416,9 @@ declare class KubernetesBuilder {
|
|
|
392
416
|
setFetcher(fetcher?: KubernetesFetcher): this;
|
|
393
417
|
setServiceLocator(serviceLocator?: KubernetesServiceLocator): this;
|
|
394
418
|
setProxy(proxy?: KubernetesProxy): this;
|
|
419
|
+
setAuthTranslatorMap(authTranslatorMap: {
|
|
420
|
+
[key: string]: KubernetesAuthTranslator;
|
|
421
|
+
}): void;
|
|
395
422
|
protected buildCustomResources(): CustomResource[];
|
|
396
423
|
protected buildClusterSupplier(refreshInterval: Duration): KubernetesClustersSupplier;
|
|
397
424
|
protected buildObjectsProvider(options: KubernetesObjectsProviderOptions): KubernetesObjectsProvider;
|
|
@@ -401,6 +428,9 @@ declare class KubernetesBuilder {
|
|
|
401
428
|
protected buildHttpServiceLocator(_clusterSupplier: KubernetesClustersSupplier): KubernetesServiceLocator;
|
|
402
429
|
protected buildProxy(logger: Logger, clusterSupplier: KubernetesClustersSupplier): KubernetesProxy;
|
|
403
430
|
protected buildRouter(objectsProvider: KubernetesObjectsProvider, clusterSupplier: KubernetesClustersSupplier, catalogApi: CatalogApi, proxy: KubernetesProxy, permissionApi: PermissionEvaluator): express.Router;
|
|
431
|
+
protected buildAuthTranslatorMap(): {
|
|
432
|
+
[key: string]: KubernetesAuthTranslator;
|
|
433
|
+
};
|
|
404
434
|
protected fetchClusterDetails(clusterSupplier: KubernetesClustersSupplier): Promise<ClusterDetails[]>;
|
|
405
435
|
protected getServiceLocatorMethod(): ServiceLocatorMethod;
|
|
406
436
|
protected getFetcher(): KubernetesFetcher;
|
|
@@ -409,6 +439,9 @@ declare class KubernetesBuilder {
|
|
|
409
439
|
protected getObjectsProvider(options: KubernetesObjectsProviderOptions): KubernetesObjectsProvider;
|
|
410
440
|
protected getObjectTypesToFetch(): ObjectToFetch[] | undefined;
|
|
411
441
|
protected getProxy(logger: Logger, clusterSupplier: KubernetesClustersSupplier): KubernetesProxy;
|
|
442
|
+
protected getAuthTranslatorMap(): {
|
|
443
|
+
[key: string]: KubernetesAuthTranslator;
|
|
444
|
+
};
|
|
412
445
|
}
|
|
413
446
|
|
|
414
447
|
/**
|
|
@@ -446,4 +479,4 @@ interface RouterOptions {
|
|
|
446
479
|
*/
|
|
447
480
|
declare function createRouter(options: RouterOptions): Promise<express.Router>;
|
|
448
481
|
|
|
449
|
-
export { AWSClusterDetails, AwsIamKubernetesAuthTranslator, AzureClusterDetails, AzureIdentityKubernetesAuthTranslator, ClusterDetails, CustomResource, CustomResourcesByEntity, DEFAULT_OBJECTS, FetchResponseWrapper, GKEClusterDetails, GoogleKubernetesAuthTranslator, GoogleServiceAccountAuthTranslator, HEADER_KUBERNETES_AUTH, HEADER_KUBERNETES_CLUSTER, KubernetesAuthTranslator,
|
|
482
|
+
export { AWSClusterDetails, AwsIamKubernetesAuthTranslator, AzureClusterDetails, AzureIdentityKubernetesAuthTranslator, ClusterDetails, CustomResource, CustomResourcesByEntity, DEFAULT_OBJECTS, DispatchingKubernetesAuthTranslator, DispatchingKubernetesAuthTranslatorOptions, FetchResponseWrapper, GKEClusterDetails, GoogleKubernetesAuthTranslator, GoogleServiceAccountAuthTranslator, HEADER_KUBERNETES_AUTH, HEADER_KUBERNETES_CLUSTER, KubernetesAuthTranslator, KubernetesBuilder, KubernetesBuilderReturn, KubernetesClustersSupplier, KubernetesEnvironment, KubernetesFetcher, KubernetesObjectTypes, KubernetesObjectsByEntity, KubernetesObjectsProvider, KubernetesObjectsProviderOptions, KubernetesProxy, KubernetesProxyCreateRequestHandlerOptions, KubernetesProxyOptions, KubernetesServiceLocator, NoopKubernetesAuthTranslator, ObjectFetchParams, ObjectToFetch, ObjectsByEntityRequest, OidcKubernetesAuthTranslator, RouterOptions, ServiceAccountClusterDetails, ServiceLocatorMethod, ServiceLocatorRequestContext, SigningCreds, createRouter };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-kubernetes-backend",
|
|
3
3
|
"description": "A Backstage backend plugin that integrates towards Kubernetes",
|
|
4
|
-
"version": "0.10.0-next.
|
|
4
|
+
"version": "0.10.0-next.2",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -48,17 +48,17 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@azure/identity": "^2.0.4",
|
|
51
|
-
"@backstage/backend-common": "^0.18.4-next.
|
|
52
|
-
"@backstage/backend-plugin-api": "^0.5.1-next.
|
|
53
|
-
"@backstage/catalog-client": "^1.4.0",
|
|
51
|
+
"@backstage/backend-common": "^0.18.4-next.2",
|
|
52
|
+
"@backstage/backend-plugin-api": "^0.5.1-next.2",
|
|
53
|
+
"@backstage/catalog-client": "^1.4.1-next.0",
|
|
54
54
|
"@backstage/catalog-model": "^1.2.1",
|
|
55
55
|
"@backstage/config": "^1.0.7",
|
|
56
56
|
"@backstage/errors": "^1.1.5",
|
|
57
|
-
"@backstage/plugin-auth-node": "^0.2.13-next.
|
|
58
|
-
"@backstage/plugin-catalog-node": "^1.3.5-next.
|
|
57
|
+
"@backstage/plugin-auth-node": "^0.2.13-next.2",
|
|
58
|
+
"@backstage/plugin-catalog-node": "^1.3.5-next.2",
|
|
59
59
|
"@backstage/plugin-kubernetes-common": "^0.6.2-next.1",
|
|
60
60
|
"@backstage/plugin-permission-common": "^0.7.5-next.0",
|
|
61
|
-
"@backstage/plugin-permission-node": "^0.7.7-next.
|
|
61
|
+
"@backstage/plugin-permission-node": "^0.7.7-next.2",
|
|
62
62
|
"@google-cloud/container": "^4.0.0",
|
|
63
63
|
"@jest-mock/express": "^2.0.1",
|
|
64
64
|
"@kubernetes/client-node": "0.18.1",
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
"yn": "^4.0.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@backstage/backend-test-utils": "^0.1.36-next.
|
|
86
|
-
"@backstage/cli": "^0.22.6-next.
|
|
85
|
+
"@backstage/backend-test-utils": "^0.1.36-next.2",
|
|
86
|
+
"@backstage/cli": "^0.22.6-next.2",
|
|
87
87
|
"@types/aws4": "^1.5.1",
|
|
88
88
|
"@types/http-proxy-middleware": "^0.19.3",
|
|
89
89
|
"aws-sdk-mock": "^5.2.1",
|