@backstage/plugin-kubernetes-backend 0.5.1 → 0.6.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 +29 -0
- package/dist/index.cjs.js +60 -7
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @backstage/plugin-kubernetes-backend
|
|
2
2
|
|
|
3
|
+
## 0.6.0-next.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/backend-common@0.14.0-next.2
|
|
9
|
+
|
|
10
|
+
## 0.6.0-next.1
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @backstage/backend-common@0.13.6-next.1
|
|
16
|
+
- @backstage/catalog-model@1.0.3-next.0
|
|
17
|
+
- @backstage/plugin-kubernetes-common@0.3.0-next.1
|
|
18
|
+
|
|
19
|
+
## 0.6.0-next.0
|
|
20
|
+
|
|
21
|
+
### Minor Changes
|
|
22
|
+
|
|
23
|
+
- 4328737af6: Add support to fetch data for Stateful Sets from Kubernetes
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- 0c70cd8e1d: cache and refresh Azure tokens to avoid excessive calls to Azure Identity
|
|
28
|
+
- Updated dependencies
|
|
29
|
+
- @backstage/backend-common@0.13.6-next.0
|
|
30
|
+
- @backstage/plugin-kubernetes-common@0.3.0-next.0
|
|
31
|
+
|
|
3
32
|
## 0.5.1
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -400,13 +400,51 @@ class GoogleServiceAccountAuthTranslator {
|
|
|
400
400
|
|
|
401
401
|
const aksScope = "6dae42f8-4368-4678-94ff-3960e28e3630/.default";
|
|
402
402
|
class AzureIdentityKubernetesAuthTranslator {
|
|
403
|
+
constructor(logger, tokenCredential = new identity.DefaultAzureCredential()) {
|
|
404
|
+
this.logger = logger;
|
|
405
|
+
this.tokenCredential = tokenCredential;
|
|
406
|
+
this.accessToken = { token: "", expiresOnTimestamp: 0 };
|
|
407
|
+
}
|
|
403
408
|
async decorateClusterDetailsWithAuth(clusterDetails) {
|
|
404
409
|
const clusterDetailsWithAuthToken = Object.assign({}, clusterDetails);
|
|
405
|
-
|
|
406
|
-
const accessToken = await credentials.getToken(aksScope);
|
|
407
|
-
clusterDetailsWithAuthToken.serviceAccountToken = accessToken.token;
|
|
410
|
+
clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();
|
|
408
411
|
return clusterDetailsWithAuthToken;
|
|
409
412
|
}
|
|
413
|
+
async getToken() {
|
|
414
|
+
if (!this.tokenRequiresRefresh()) {
|
|
415
|
+
return this.accessToken.token;
|
|
416
|
+
}
|
|
417
|
+
if (!this.newTokenPromise) {
|
|
418
|
+
this.newTokenPromise = this.fetchNewToken();
|
|
419
|
+
}
|
|
420
|
+
return this.newTokenPromise;
|
|
421
|
+
}
|
|
422
|
+
async fetchNewToken() {
|
|
423
|
+
try {
|
|
424
|
+
this.logger.info("Fetching new Azure token for AKS");
|
|
425
|
+
const newAccessToken = await this.tokenCredential.getToken(aksScope, {
|
|
426
|
+
requestOptions: { timeout: 1e4 }
|
|
427
|
+
});
|
|
428
|
+
if (!newAccessToken) {
|
|
429
|
+
throw new Error("AccessToken is null");
|
|
430
|
+
}
|
|
431
|
+
this.accessToken = newAccessToken;
|
|
432
|
+
} catch (err) {
|
|
433
|
+
this.logger.error("Unable to fetch Azure token", err);
|
|
434
|
+
if (this.tokenExpired()) {
|
|
435
|
+
throw err;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
this.newTokenPromise = void 0;
|
|
439
|
+
return this.accessToken.token;
|
|
440
|
+
}
|
|
441
|
+
tokenRequiresRefresh() {
|
|
442
|
+
const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1e3;
|
|
443
|
+
return Date.now() >= expiresOn;
|
|
444
|
+
}
|
|
445
|
+
tokenExpired() {
|
|
446
|
+
return Date.now() >= this.accessToken.expiresOnTimestamp;
|
|
447
|
+
}
|
|
410
448
|
}
|
|
411
449
|
|
|
412
450
|
class OidcKubernetesAuthTranslator {
|
|
@@ -428,7 +466,7 @@ class OidcKubernetesAuthTranslator {
|
|
|
428
466
|
}
|
|
429
467
|
|
|
430
468
|
class KubernetesAuthTranslatorGenerator {
|
|
431
|
-
static getKubernetesAuthTranslatorInstance(authProvider) {
|
|
469
|
+
static getKubernetesAuthTranslatorInstance(authProvider, options) {
|
|
432
470
|
switch (authProvider) {
|
|
433
471
|
case "google": {
|
|
434
472
|
return new GoogleKubernetesAuthTranslator();
|
|
@@ -437,7 +475,7 @@ class KubernetesAuthTranslatorGenerator {
|
|
|
437
475
|
return new AwsIamKubernetesAuthTranslator();
|
|
438
476
|
}
|
|
439
477
|
case "azure": {
|
|
440
|
-
return new AzureIdentityKubernetesAuthTranslator();
|
|
478
|
+
return new AzureIdentityKubernetesAuthTranslator(options.logger);
|
|
441
479
|
}
|
|
442
480
|
case "serviceAccount": {
|
|
443
481
|
return new ServiceAccountKubernetesAuthTranslator();
|
|
@@ -509,6 +547,12 @@ const DEFAULT_OBJECTS = [
|
|
|
509
547
|
apiVersion: "v1",
|
|
510
548
|
plural: "ingresses",
|
|
511
549
|
objectType: "ingresses"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
group: "apps",
|
|
553
|
+
apiVersion: "v1",
|
|
554
|
+
plural: "statefulsets",
|
|
555
|
+
objectType: "statefulsets"
|
|
512
556
|
}
|
|
513
557
|
];
|
|
514
558
|
const isPodFetchResponse = (fr) => fr.type === "pods";
|
|
@@ -553,14 +597,14 @@ class KubernetesFanOutHandler {
|
|
|
553
597
|
this.serviceLocator = serviceLocator;
|
|
554
598
|
this.customResources = customResources;
|
|
555
599
|
this.objectTypesToFetch = new Set(objectTypesToFetch);
|
|
600
|
+
this.authTranslators = {};
|
|
556
601
|
}
|
|
557
602
|
async getKubernetesObjectsByEntity(requestBody) {
|
|
558
603
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
559
604
|
const entityName = ((_c = (_b = (_a = requestBody.entity) == null ? void 0 : _a.metadata) == null ? void 0 : _b.annotations) == null ? void 0 : _c["backstage.io/kubernetes-id"]) || ((_e = (_d = requestBody.entity) == null ? void 0 : _d.metadata) == null ? void 0 : _e.name);
|
|
560
605
|
const clusterDetails = await this.serviceLocator.getClustersByServiceId(entityName);
|
|
561
606
|
const promises = clusterDetails.map((cd) => {
|
|
562
|
-
|
|
563
|
-
return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(cd, requestBody);
|
|
607
|
+
return this.getAuthTranslator(cd.authProvider).decorateClusterDetailsWithAuth(cd, requestBody);
|
|
564
608
|
});
|
|
565
609
|
const clusterDetailsDecoratedForAuth = await Promise.all(promises);
|
|
566
610
|
this.logger.info(`entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth.map((c) => c.name).join(", ")}]`);
|
|
@@ -613,6 +657,15 @@ class KubernetesFanOutHandler {
|
|
|
613
657
|
const podMetrics = Array.from(namespaces).map((ns) => this.fetcher.fetchPodMetricsByNamespace(clusterDetails, ns));
|
|
614
658
|
return Promise.all([result, Promise.all(podMetrics)]);
|
|
615
659
|
}
|
|
660
|
+
getAuthTranslator(provider) {
|
|
661
|
+
if (this.authTranslators[provider]) {
|
|
662
|
+
return this.authTranslators[provider];
|
|
663
|
+
}
|
|
664
|
+
this.authTranslators[provider] = KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(provider, {
|
|
665
|
+
logger: this.logger
|
|
666
|
+
});
|
|
667
|
+
return this.authTranslators[provider];
|
|
668
|
+
}
|
|
616
669
|
}
|
|
617
670
|
|
|
618
671
|
const isError = (fr) => fr.hasOwnProperty("errorType");
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/index.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesClientProvider.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/ServiceAccountKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\n );\n }\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async getClustersByServiceId(_serviceId: string): Promise<ClusterDetails[]> {\n return this.clusterSupplier.getClusters();\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CoreV1Api,\n KubeConfig,\n Metrics,\n CustomObjectsApi,\n} from '@kubernetes/client-node';\nimport { ClusterDetails } from '../types/types';\n\nexport class KubernetesClientProvider {\n // visible for testing\n getKubeConfig(clusterDetails: ClusterDetails) {\n const cluster = {\n name: clusterDetails.name,\n server: clusterDetails.url,\n skipTLSVerify: clusterDetails.skipTLSVerify,\n caData: clusterDetails.caData,\n };\n\n // TODO configure\n const user = {\n name: 'backstage',\n token: clusterDetails.serviceAccountToken,\n };\n\n const context = {\n name: `${clusterDetails.name}`,\n user: user.name,\n cluster: cluster.name,\n };\n\n const kc = new KubeConfig();\n if (clusterDetails.serviceAccountToken) {\n kc.loadFromOptions({\n clusters: [cluster],\n users: [user],\n contexts: [context],\n currentContext: context.name,\n });\n } else {\n kc.loadFromDefault();\n }\n\n return kc;\n }\n\n getCoreClientByClusterDetails(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CoreV1Api);\n }\n\n getMetricsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return new Metrics(kc);\n }\n\n getCustomObjectsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CustomObjectsApi);\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n requestBody: KubernetesRequestBody,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = requestBody.auth?.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class ServiceAccountKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n _requestBody: KubernetesRequestBody,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\ntype SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n return new Promise<SigningCreds>(async (resolve, reject) => {\n const awsCreds = await this.awsGetCredentials();\n\n if (!(awsCreds instanceof Credentials))\n return reject(Error('No AWS credentials found.'));\n\n let creds: SigningCreds = {\n accessKeyId: awsCreds.accessKeyId,\n secretAccessKey: awsCreds.secretAccessKey,\n sessionToken: awsCreds.sessionToken,\n };\n\n if (!this.validCredentials(creds))\n return reject(Error('Invalid AWS credentials found.'));\n if (!assumeRole) return resolve(creds);\n\n try {\n const params: AWS.STS.Types.AssumeRoleRequest = {\n RoleArn: assumeRole,\n RoleSessionName: 'backstage-login',\n };\n if (externalId) params.ExternalId = externalId;\n\n const assumedRole = await new AWS.STS().assumeRole(params).promise();\n\n if (!assumedRole.Credentials) {\n throw new Error(`No credentials returned for role ${assumeRole}`);\n }\n\n creds = {\n accessKeyId: assumedRole.Credentials.AccessKeyId,\n secretAccessKey: assumedRole.Credentials.SecretAccessKey,\n sessionToken: assumedRole.Credentials.SessionToken,\n };\n } catch (e) {\n console.warn(`There was an error assuming the role: ${e}`);\n return reject(Error(`Unable to assume role: ${e}`));\n }\n return resolve(creds);\n });\n }\n async getBearerToken(\n clusterName: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const credentials = await this.getCredentials(assumeRole, externalId);\n\n const request = {\n host: `sts.amazonaws.com`,\n path: `/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Expires=60`,\n headers: {\n 'x-k8s-aws-id': clusterName,\n },\n signQuery: true,\n };\n\n const signed = sign(request, credentials);\n const url = `https://${signed.host}${signed.path}`;\n const base64Url = Buffer.from(url, 'binary').toString('base64');\n const urlSafeBase64Url = base64Url\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return `k8s-aws-v1.${urlSafeBase64Url}`;\n }\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AWSClusterDetails,\n ): Promise<AWSClusterDetails> {\n const clusterDetailsWithAuthToken: AWSClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getBearerToken(\n clusterDetails.name,\n clusterDetails.assumeRole,\n clusterDetails.externalId,\n );\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport { DefaultAzureCredential } from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const credentials = new DefaultAzureCredential();\n\n // TODO: can we cache this? It's inneficiant to get a new token every time\n const accessToken = await credentials.getToken(aksScope);\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken.token;\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/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n requestBody: KubernetesRequestBody,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined =\n requestBody.auth?.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { ServiceAccountKubernetesAuthTranslator } from './ServiceAccountKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n ): 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();\n }\n case 'serviceAccount': {\n return new ServiceAccountKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\n }\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n CustomResource,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\nexport const DEFAULT_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'pods',\n objectType: 'pods',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'services',\n objectType: 'services',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'configmaps',\n objectType: 'configmaps',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: PodStatus[][],\n): ClientPodStatus[] => {\n return podMetrics.flat().map((pd: PodStatus): ClientPodStatus => {\n return {\n pod: pd.Pod,\n memory: toClientSafeResource(pd.Memory),\n cpu: toClientSafeResource(pd.CPU),\n containers: pd.Containers.map(toClientSafeContainer),\n };\n });\n};\n\ntype responseWithMetrics = [FetchResponseWrapper, PodStatus[][]];\n\nexport class KubernetesFanOutHandler {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n\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 }\n\n async getKubernetesObjectsByEntity(\n requestBody: KubernetesRequestBody,\n ): Promise<ObjectsByEntityResponse> {\n const entityName =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-id'\n ] || requestBody.entity?.metadata?.name;\n\n const clusterDetails: ClusterDetails[] =\n await this.serviceLocator.getClustersByServiceId(entityName);\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n const promises: Promise<ClusterDetails>[] = clusterDetails.map(cd => {\n const kubernetesAuthTranslator: KubernetesAuthTranslator =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n cd.authProvider,\n );\n return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(\n cd,\n requestBody,\n );\n });\n const clusterDetailsDecoratedForAuth: ClusterDetails[] = await Promise.all(\n promises,\n );\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-namespace'\n ];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: this.objectTypesToFetch,\n labelSelector,\n customResources: this.customResources,\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\n .then(r => this.toClusterObjects(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n const podMetrics = Array.from(namespaces).map(ns =>\n this.fetcher.fetchPodMetricsByNamespace(clusterDetails, ns),\n );\n\n return Promise.all([result, Promise.all(podMetrics)]);\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CoreV1Api, topPods } from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n KubernetesObjectTypes,\n ObjectFetchParams,\n ObjectToFetch,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\n} from '@backstage/plugin-kubernetes-common';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport { PodStatus } from '@kubernetes/client-node/dist/top';\n\nexport interface Clients {\n core: CoreV1Api;\n}\n\nexport interface KubernetesClientBasedFetcherOptions {\n kubernetesClientProvider: KubernetesClientProvider;\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly kubernetesClientProvider: KubernetesClientProvider;\n private readonly logger: Logger;\n\n constructor({\n kubernetesClientProvider,\n logger,\n }: KubernetesClientBasedFetcherOptions) {\n this.kubernetesClientProvider = kubernetesClientProvider;\n this.logger = logger;\n }\n\n fetchObjectsForService(\n params: ObjectFetchParams,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(params.objectTypesToFetch)\n .concat(params.customResources)\n .map(toFetch => {\n return this.fetchResource(\n params.clusterDetails,\n toFetch,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n toFetch.objectType,\n params.namespace,\n ).catch(this.captureKubernetesErrorsRethrowOthers.bind(this));\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespace(\n clusterDetails: ClusterDetails,\n namespace: string,\n ): Promise<PodStatus[]> {\n const metricsClient =\n this.kubernetesClientProvider.getMetricsClient(clusterDetails);\n const coreApi =\n this.kubernetesClientProvider.getCoreClientByClusterDetails(\n clusterDetails,\n );\n\n return topPods(coreApi, metricsClient, namespace);\n }\n\n private captureKubernetesErrorsRethrowOthers(e: any): KubernetesFetchError {\n if (e.response && e.response.statusCode) {\n this.logger.warn(\n `statusCode=${e.response.statusCode} for resource ${\n e.response.request.uri.pathname\n } body=[${JSON.stringify(e.response.body)}]`,\n );\n return {\n errorType: statusCodeToErrorType(e.response.statusCode),\n statusCode: e.response.statusCode,\n resourcePath: e.response.request.uri.pathname,\n };\n }\n throw e;\n }\n\n private fetchResource(\n clusterDetails: ClusterDetails,\n resource: ObjectToFetch,\n labelSelector: string,\n objectType: KubernetesObjectTypes,\n namespace?: string,\n ): Promise<FetchResponse> {\n const customObjects =\n this.kubernetesClientProvider.getCustomObjectsClient(clusterDetails);\n\n customObjects.addInterceptor((requestOptions: any) => {\n requestOptions.uri = requestOptions.uri.replace('/apis//v1/', '/api/v1/');\n });\n\n if (namespace) {\n return customObjects\n .listNamespacedCustomObject(\n resource.group,\n resource.apiVersion,\n namespace,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n return customObjects\n .listClusterCustomObject(\n resource.group,\n resource.apiVersion,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport { Duration } from 'luxon';\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n KubernetesObjectTypes,\n ServiceLocatorMethod,\n CustomResource,\n KubernetesObjectsProvider,\n ObjectsByEntityRequest,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesServiceLocator,\n KubernetesObjectsProviderOptions,\n} from '../types/types';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\n\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @public\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.fetcher ?? this.buildFetcher();\n\n const clusterSupplier =\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval);\n\n const serviceLocator =\n this.serviceLocator ??\n this.buildServiceLocator(this.getServiceLocatorMethod(), clusterSupplier);\n\n const objectsProvider =\n this.objectsProvider ??\n this.buildObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(objectsProvider, clusterSupplier);\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n return getCombinedClusterSupplier(config, refreshInterval);\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n return new KubernetesFanOutHandler(options);\n }\n\n protected buildFetcher(): KubernetesFetcher {\n return new KubernetesClientBasedFetcher({\n kubernetesClientProvider: new KubernetesClientProvider(),\n logger: this.env.logger,\n });\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n return this.buildMultiTenantServiceLocator(clusterSupplier);\n case 'http':\n return this.buildHttpServiceLocator(clusterSupplier);\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use(express.json());\n\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity(\n requestBody,\n );\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\n\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n clusterSupplier?: KubernetesClustersSupplier;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["container","ForwardedError","KubeConfig","CoreV1Api","Metrics","CustomObjectsApi","AWS","Credentials","sign","DefaultAzureCredential","lodash","topPods","Duration","Router","express"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/index.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesClientProvider.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/ServiceAccountKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\n );\n }\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async getClustersByServiceId(_serviceId: string): Promise<ClusterDetails[]> {\n return this.clusterSupplier.getClusters();\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CoreV1Api,\n KubeConfig,\n Metrics,\n CustomObjectsApi,\n} from '@kubernetes/client-node';\nimport { ClusterDetails } from '../types/types';\n\nexport class KubernetesClientProvider {\n // visible for testing\n getKubeConfig(clusterDetails: ClusterDetails) {\n const cluster = {\n name: clusterDetails.name,\n server: clusterDetails.url,\n skipTLSVerify: clusterDetails.skipTLSVerify,\n caData: clusterDetails.caData,\n };\n\n // TODO configure\n const user = {\n name: 'backstage',\n token: clusterDetails.serviceAccountToken,\n };\n\n const context = {\n name: `${clusterDetails.name}`,\n user: user.name,\n cluster: cluster.name,\n };\n\n const kc = new KubeConfig();\n if (clusterDetails.serviceAccountToken) {\n kc.loadFromOptions({\n clusters: [cluster],\n users: [user],\n contexts: [context],\n currentContext: context.name,\n });\n } else {\n kc.loadFromDefault();\n }\n\n return kc;\n }\n\n getCoreClientByClusterDetails(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CoreV1Api);\n }\n\n getMetricsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return new Metrics(kc);\n }\n\n getCustomObjectsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CustomObjectsApi);\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n requestBody: KubernetesRequestBody,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = requestBody.auth?.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class ServiceAccountKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n _requestBody: KubernetesRequestBody,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\ntype SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n return new Promise<SigningCreds>(async (resolve, reject) => {\n const awsCreds = await this.awsGetCredentials();\n\n if (!(awsCreds instanceof Credentials))\n return reject(Error('No AWS credentials found.'));\n\n let creds: SigningCreds = {\n accessKeyId: awsCreds.accessKeyId,\n secretAccessKey: awsCreds.secretAccessKey,\n sessionToken: awsCreds.sessionToken,\n };\n\n if (!this.validCredentials(creds))\n return reject(Error('Invalid AWS credentials found.'));\n if (!assumeRole) return resolve(creds);\n\n try {\n const params: AWS.STS.Types.AssumeRoleRequest = {\n RoleArn: assumeRole,\n RoleSessionName: 'backstage-login',\n };\n if (externalId) params.ExternalId = externalId;\n\n const assumedRole = await new AWS.STS().assumeRole(params).promise();\n\n if (!assumedRole.Credentials) {\n throw new Error(`No credentials returned for role ${assumeRole}`);\n }\n\n creds = {\n accessKeyId: assumedRole.Credentials.AccessKeyId,\n secretAccessKey: assumedRole.Credentials.SecretAccessKey,\n sessionToken: assumedRole.Credentials.SessionToken,\n };\n } catch (e) {\n console.warn(`There was an error assuming the role: ${e}`);\n return reject(Error(`Unable to assume role: ${e}`));\n }\n return resolve(creds);\n });\n }\n async getBearerToken(\n clusterName: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const credentials = await this.getCredentials(assumeRole, externalId);\n\n const request = {\n host: `sts.amazonaws.com`,\n path: `/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Expires=60`,\n headers: {\n 'x-k8s-aws-id': clusterName,\n },\n signQuery: true,\n };\n\n const signed = sign(request, credentials);\n const url = `https://${signed.host}${signed.path}`;\n const base64Url = Buffer.from(url, 'binary').toString('base64');\n const urlSafeBase64Url = base64Url\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return `k8s-aws-v1.${urlSafeBase64Url}`;\n }\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AWSClusterDetails,\n ): Promise<AWSClusterDetails> {\n const clusterDetailsWithAuthToken: AWSClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getBearerToken(\n clusterDetails.name,\n clusterDetails.assumeRole,\n clusterDetails.externalId,\n );\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';\n\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n requestBody: KubernetesRequestBody,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined =\n requestBody.auth?.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { ServiceAccountKubernetesAuthTranslator } from './ServiceAccountKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n options: {\n logger: Logger;\n },\n ): KubernetesAuthTranslator {\n switch (authProvider) {\n case 'google': {\n return new GoogleKubernetesAuthTranslator();\n }\n case 'aws': {\n return new AwsIamKubernetesAuthTranslator();\n }\n case 'azure': {\n return new AzureIdentityKubernetesAuthTranslator(options.logger);\n }\n case 'serviceAccount': {\n return new ServiceAccountKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\n }\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n CustomResource,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\nexport const DEFAULT_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'pods',\n objectType: 'pods',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'services',\n objectType: 'services',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'configmaps',\n objectType: 'configmaps',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: PodStatus[][],\n): ClientPodStatus[] => {\n return podMetrics.flat().map((pd: PodStatus): ClientPodStatus => {\n return {\n pod: pd.Pod,\n memory: toClientSafeResource(pd.Memory),\n cpu: toClientSafeResource(pd.CPU),\n containers: pd.Containers.map(toClientSafeContainer),\n };\n });\n};\n\ntype responseWithMetrics = [FetchResponseWrapper, PodStatus[][]];\n\nexport class KubernetesFanOutHandler {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslators: Record<string, KubernetesAuthTranslator>;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n }: KubernetesFanOutHandlerOptions) {\n this.logger = logger;\n this.fetcher = fetcher;\n this.serviceLocator = serviceLocator;\n this.customResources = customResources;\n this.objectTypesToFetch = new Set(objectTypesToFetch);\n this.authTranslators = {};\n }\n\n async getKubernetesObjectsByEntity(\n requestBody: KubernetesRequestBody,\n ): Promise<ObjectsByEntityResponse> {\n const entityName =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-id'\n ] || requestBody.entity?.metadata?.name;\n\n const clusterDetails: ClusterDetails[] =\n await this.serviceLocator.getClustersByServiceId(entityName);\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n const promises: Promise<ClusterDetails>[] = clusterDetails.map(cd => {\n return this.getAuthTranslator(\n cd.authProvider,\n ).decorateClusterDetailsWithAuth(cd, requestBody);\n });\n const clusterDetailsDecoratedForAuth: ClusterDetails[] = await Promise.all(\n promises,\n );\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n requestBody.entity?.metadata?.annotations?.[\n 'backstage.io/kubernetes-namespace'\n ];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: this.objectTypesToFetch,\n labelSelector,\n customResources: this.customResources,\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\n .then(r => this.toClusterObjects(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n const podMetrics = Array.from(namespaces).map(ns =>\n this.fetcher.fetchPodMetricsByNamespace(clusterDetails, ns),\n );\n\n return Promise.all([result, Promise.all(podMetrics)]);\n }\n\n private getAuthTranslator(provider: string): KubernetesAuthTranslator {\n if (this.authTranslators[provider]) {\n return this.authTranslators[provider];\n }\n\n this.authTranslators[provider] =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n provider,\n {\n logger: this.logger,\n },\n );\n return this.authTranslators[provider];\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CoreV1Api, topPods } from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n KubernetesObjectTypes,\n ObjectFetchParams,\n ObjectToFetch,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\n} from '@backstage/plugin-kubernetes-common';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport { PodStatus } from '@kubernetes/client-node/dist/top';\n\nexport interface Clients {\n core: CoreV1Api;\n}\n\nexport interface KubernetesClientBasedFetcherOptions {\n kubernetesClientProvider: KubernetesClientProvider;\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly kubernetesClientProvider: KubernetesClientProvider;\n private readonly logger: Logger;\n\n constructor({\n kubernetesClientProvider,\n logger,\n }: KubernetesClientBasedFetcherOptions) {\n this.kubernetesClientProvider = kubernetesClientProvider;\n this.logger = logger;\n }\n\n fetchObjectsForService(\n params: ObjectFetchParams,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(params.objectTypesToFetch)\n .concat(params.customResources)\n .map(toFetch => {\n return this.fetchResource(\n params.clusterDetails,\n toFetch,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n toFetch.objectType,\n params.namespace,\n ).catch(this.captureKubernetesErrorsRethrowOthers.bind(this));\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespace(\n clusterDetails: ClusterDetails,\n namespace: string,\n ): Promise<PodStatus[]> {\n const metricsClient =\n this.kubernetesClientProvider.getMetricsClient(clusterDetails);\n const coreApi =\n this.kubernetesClientProvider.getCoreClientByClusterDetails(\n clusterDetails,\n );\n\n return topPods(coreApi, metricsClient, namespace);\n }\n\n private captureKubernetesErrorsRethrowOthers(e: any): KubernetesFetchError {\n if (e.response && e.response.statusCode) {\n this.logger.warn(\n `statusCode=${e.response.statusCode} for resource ${\n e.response.request.uri.pathname\n } body=[${JSON.stringify(e.response.body)}]`,\n );\n return {\n errorType: statusCodeToErrorType(e.response.statusCode),\n statusCode: e.response.statusCode,\n resourcePath: e.response.request.uri.pathname,\n };\n }\n throw e;\n }\n\n private fetchResource(\n clusterDetails: ClusterDetails,\n resource: ObjectToFetch,\n labelSelector: string,\n objectType: KubernetesObjectTypes,\n namespace?: string,\n ): Promise<FetchResponse> {\n const customObjects =\n this.kubernetesClientProvider.getCustomObjectsClient(clusterDetails);\n\n customObjects.addInterceptor((requestOptions: any) => {\n requestOptions.uri = requestOptions.uri.replace('/apis//v1/', '/api/v1/');\n });\n\n if (namespace) {\n return customObjects\n .listNamespacedCustomObject(\n resource.group,\n resource.apiVersion,\n namespace,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n return customObjects\n .listClusterCustomObject(\n resource.group,\n resource.apiVersion,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport { Duration } from 'luxon';\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n KubernetesObjectTypes,\n ServiceLocatorMethod,\n CustomResource,\n KubernetesObjectsProvider,\n ObjectsByEntityRequest,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesServiceLocator,\n KubernetesObjectsProviderOptions,\n} from '../types/types';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\n\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @public\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.fetcher ?? this.buildFetcher();\n\n const clusterSupplier =\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval);\n\n const serviceLocator =\n this.serviceLocator ??\n this.buildServiceLocator(this.getServiceLocatorMethod(), clusterSupplier);\n\n const objectsProvider =\n this.objectsProvider ??\n this.buildObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(objectsProvider, clusterSupplier);\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n return getCombinedClusterSupplier(config, refreshInterval);\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n return new KubernetesFanOutHandler(options);\n }\n\n protected buildFetcher(): KubernetesFetcher {\n return new KubernetesClientBasedFetcher({\n kubernetesClientProvider: new KubernetesClientProvider(),\n logger: this.env.logger,\n });\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n return this.buildMultiTenantServiceLocator(clusterSupplier);\n case 'http':\n return this.buildHttpServiceLocator(clusterSupplier);\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use(express.json());\n\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity(\n requestBody,\n );\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\n\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n clusterSupplier?: KubernetesClustersSupplier;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["container","ForwardedError","KubeConfig","CoreV1Api","Metrics","CustomObjectsApi","AWS","Credentials","sign","DefaultAzureCredential","lodash","topPods","Duration","Router","express"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAO,MAAM,oBAAoB,CAAC;AAClC,EAAE,WAAW,CAAC,cAAc,EAAE;AAC9B,IAAI,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;AACzC,GAAG;AACH,EAAE,OAAO,UAAU,CAAC,MAAM,EAAE;AAC5B,IAAI,OAAO,IAAI,oBAAoB,CAAC,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK;AACjF,MAAM,IAAI,EAAE,EAAE,EAAE,CAAC;AACjB,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;AACvD,MAAM,MAAM,cAAc,GAAG;AAC7B,QAAQ,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC;AACjC,QAAQ,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC;AAC/B,QAAQ,mBAAmB,EAAE,CAAC,CAAC,iBAAiB,CAAC,qBAAqB,CAAC;AACvE,QAAQ,aAAa,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,kBAAkB,CAAC,eAAe,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,KAAK;AACxF,QAAQ,iBAAiB,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,KAAK;AAChG,QAAQ,MAAM,EAAE,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC;AAC7C,QAAQ,YAAY;AACpB,OAAO,CAAC;AACR,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;AAC/D,MAAM,IAAI,YAAY,EAAE;AACxB,QAAQ,cAAc,CAAC,YAAY,GAAG,YAAY,CAAC;AACnD,OAAO;AACP,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;AAC/D,MAAM,IAAI,YAAY,EAAE;AACxB,QAAQ,cAAc,CAAC,YAAY,GAAG,YAAY,CAAC;AACnD,OAAO;AACP,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE;AACxC,QAAQ,cAAc,CAAC,mBAAmB,GAAG,CAAC,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;AAC1E,OAAO;AACP,MAAM,QAAQ,YAAY;AAC1B,QAAQ,KAAK,QAAQ,EAAE;AACvB,UAAU,OAAO,cAAc,CAAC;AAChC,SAAS;AACT,QAAQ,KAAK,KAAK,EAAE;AACpB,UAAU,MAAM,UAAU,GAAG,CAAC,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAC/D,UAAU,MAAM,UAAU,GAAG,CAAC,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;AAC/D,UAAU,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,cAAc,EAAE,CAAC;AAC/D,SAAS;AACT,QAAQ,KAAK,OAAO,EAAE;AACtB,UAAU,OAAO,cAAc,CAAC;AAChC,SAAS;AACT,QAAQ,KAAK,MAAM,EAAE;AACrB,UAAU,MAAM,iBAAiB,GAAG,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;AACrE,UAAU,OAAO,EAAE,iBAAiB,EAAE,GAAG,cAAc,EAAE,CAAC;AAC1D,SAAS;AACT,QAAQ,KAAK,gBAAgB,EAAE;AAC/B,UAAU,OAAO,cAAc,CAAC;AAChC,SAAS;AACT,QAAQ,KAAK,sBAAsB,EAAE;AACrC,UAAU,OAAO,cAAc,CAAC;AAChC,SAAS;AACT,QAAQ,SAAS;AACjB,UAAU,MAAM,IAAI,KAAK,CAAC,CAAC,cAAc,EAAE,YAAY,CAAC,kCAAkC,CAAC,CAAC,CAAC;AAC7F,SAAS;AACT,OAAO;AACP,KAAK,CAAC,CAAC,CAAC;AACR,GAAG;AACH,EAAE,MAAM,WAAW,GAAG;AACtB,IAAI,OAAO,IAAI,CAAC,cAAc,CAAC;AAC/B,GAAG;AACH;;AC3DO,SAAS,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE;AAC7C,EAAE,IAAI,MAAM,CAAC;AACb,EAAE,IAAI,SAAS,GAAG,KAAK,CAAC;AACxB,EAAE,MAAM,mBAAmB,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK;AACvD,IAAI,MAAM,GAAG,MAAM;AACnB,MAAM,OAAO,EAAE,CAAC;AAChB,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,KAAK,CAAC;AACN,GAAG,CAAC,CAAC;AACL,EAAE,MAAM,YAAY,GAAG,YAAY;AACnC,IAAI,OAAO,CAAC,SAAS,EAAE;AACvB,MAAM,IAAI;AACV,QAAQ,MAAM,EAAE,EAAE,CAAC;AACnB,OAAO,CAAC,MAAM;AACd,OAAO;AACP,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC;AACzB,QAAQ,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC9D,QAAQ,mBAAmB;AAC3B,OAAO,CAAC,CAAC;AACT,KAAK;AACL,GAAG,CAAC;AACJ,EAAE,YAAY,EAAE,CAAC;AACjB,EAAE,OAAO,MAAM,CAAC;AAChB;;ACpBO,MAAM,iBAAiB,CAAC;AAC/B,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,KAAK,CAAC,EAAE,iBAAiB,GAAG,KAAK,EAAE;AACnF,IAAI,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC3B,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;AACzB,IAAI,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;AACzC,IAAI,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;AAC/C,GAAG;AACH,EAAE,OAAO,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE;AAC/D,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AAC/B,IAAI,MAAM,sBAAsB,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,sBAAsB,CAAC,wBAAwB,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AAC3I,MAAM,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;AAC1E,KAAK,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC;AAC1B,IAAI,MAAM,OAAO,GAAG;AACpB,MAAM,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC;AAC9C,MAAM,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,GAAG;AAC1E,MAAM,aAAa,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,kBAAkB,CAAC,eAAe,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,KAAK;AAC3F,MAAM,iBAAiB,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,KAAK;AACnG,MAAM,eAAe,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,KAAK;AAC/F,MAAM,sBAAsB;AAC5B,KAAK,CAAC;AACN,IAAI,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACrE,IAAI,IAAI,eAAe,EAAE;AACzB,MAAM,eAAe,CAAC,MAAM,iBAAiB,CAAC,eAAe,EAAE,EAAE,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC7F,KAAK;AACL,IAAI,OAAO,iBAAiB,CAAC;AAC7B,GAAG;AACH,EAAE,OAAO,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,KAAK,CAAC,EAAE;AACtD,IAAI,OAAO,iBAAiB,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAIA,oBAAS,CAAC,EAAE,CAAC,oBAAoB,EAAE,EAAE,eAAe,CAAC,CAAC;AACpH,GAAG;AACH,EAAE,MAAM,WAAW,GAAG;AACtB,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;AACjC,MAAM,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;AACnC,KAAK;AACL,IAAI,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,cAAc,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC;AACxD,GAAG;AACH,EAAE,MAAM,eAAe,GAAG;AAC1B,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,MAAM;AACV,MAAM,SAAS;AACf,MAAM,MAAM;AACZ,MAAM,aAAa;AACnB,MAAM,iBAAiB;AACvB,MAAM,eAAe;AACrB,MAAM,sBAAsB;AAC5B,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;AACrB,IAAI,MAAM,OAAO,GAAG;AACpB,MAAM,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AACzD,KAAK,CAAC;AACN,IAAI,IAAI;AACR,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;AACjE,MAAM,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,QAAQ,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK;AACvF,QAAQ,OAAO,sBAAsB,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK;AAC/F,UAAU,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE;AACjC,YAAY,OAAO,KAAK,CAAC;AACzB,WAAW;AACX,UAAU,OAAO,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC;AACzD,SAAS,CAAC,CAAC;AACX,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK;AACpB,QAAQ,IAAI,GAAG,EAAE,EAAE,CAAC;AACpB,QAAQ,OAAO;AACf,UAAU,IAAI,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,SAAS;AACxD,UAAU,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AAC/D,UAAU,YAAY,EAAE,QAAQ;AAChC,UAAU,aAAa;AACvB,UAAU,iBAAiB;AAC3B,UAAU,GAAG,eAAe,GAAG;AAC/B,YAAY,YAAY,EAAE,KAAK;AAC/B,YAAY,mBAAmB,EAAE;AACjC,cAAc,SAAS;AACvB,cAAc,MAAM;AACpB,cAAc,WAAW,EAAE,CAAC,CAAC,IAAI;AACjC,aAAa;AACb,WAAW,GAAG,EAAE;AAChB,SAAS,CAAC;AACV,OAAO,CAAC,CAAC;AACT,MAAM,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;AACpC,KAAK,CAAC,OAAO,CAAC,EAAE;AAChB,MAAM,MAAM,IAAIC,qBAAc,CAAC,CAAC,8DAA8D,EAAE,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACjI,KAAK;AACL,GAAG;AACH;;AClFA,MAAM,wBAAwB,CAAC;AAC/B,EAAE,WAAW,CAAC,gBAAgB,EAAE;AAChC,IAAI,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;AAC7C,GAAG;AACH,EAAE,MAAM,WAAW,GAAG;AACtB,IAAI,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK;AAC5G,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACxB,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;AACpB,MAAM,MAAM,CAAC,CAAC;AACd,KAAK,CAAC,CAAC;AACP,GAAG;AACH,CAAC;AACM,MAAM,0BAA0B,GAAG,CAAC,UAAU,EAAE,eAAe,GAAG,KAAK,CAAC,KAAK;AACpF,EAAE,MAAM,gBAAgB,GAAG,UAAU,CAAC,cAAc,CAAC,kCAAkC,CAAC,CAAC,GAAG,CAAC,CAAC,oBAAoB,KAAK;AACvH,IAAI,MAAM,IAAI,GAAG,oBAAoB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AACxD,IAAI,QAAQ,IAAI;AAChB,MAAM,KAAK,QAAQ;AACnB,QAAQ,OAAO,oBAAoB,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACrE,MAAM,KAAK,KAAK;AAChB,QAAQ,OAAO,iBAAiB,CAAC,UAAU,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;AACnF,MAAM;AACN,QAAQ,MAAM,IAAI,KAAK,CAAC,CAAC,+CAA+C,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACnF,KAAK;AACL,GAAG,CAAC,CAAC;AACL,EAAE,OAAO,IAAI,wBAAwB,CAAC,gBAAgB,CAAC,CAAC;AACxD,CAAC;;AC3BM,MAAM,yBAAyB,CAAC;AACvC,EAAE,WAAW,CAAC,eAAe,EAAE;AAC/B,IAAI,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;AAC3C,GAAG;AACH,EAAE,MAAM,sBAAsB,CAAC,UAAU,EAAE;AAC3C,IAAI,OAAO,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC;AAC9C,GAAG;AACH;;ACDO,MAAM,wBAAwB,CAAC;AACtC,EAAE,aAAa,CAAC,cAAc,EAAE;AAChC,IAAI,MAAM,OAAO,GAAG;AACpB,MAAM,IAAI,EAAE,cAAc,CAAC,IAAI;AAC/B,MAAM,MAAM,EAAE,cAAc,CAAC,GAAG;AAChC,MAAM,aAAa,EAAE,cAAc,CAAC,aAAa;AACjD,MAAM,MAAM,EAAE,cAAc,CAAC,MAAM;AACnC,KAAK,CAAC;AACN,IAAI,MAAM,IAAI,GAAG;AACjB,MAAM,IAAI,EAAE,WAAW;AACvB,MAAM,KAAK,EAAE,cAAc,CAAC,mBAAmB;AAC/C,KAAK,CAAC;AACN,IAAI,MAAM,OAAO,GAAG;AACpB,MAAM,IAAI,EAAE,CAAC,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;AACpC,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI;AACrB,MAAM,OAAO,EAAE,OAAO,CAAC,IAAI;AAC3B,KAAK,CAAC;AACN,IAAI,MAAM,EAAE,GAAG,IAAIC,qBAAU,EAAE,CAAC;AAChC,IAAI,IAAI,cAAc,CAAC,mBAAmB,EAAE;AAC5C,MAAM,EAAE,CAAC,eAAe,CAAC;AACzB,QAAQ,QAAQ,EAAE,CAAC,OAAO,CAAC;AAC3B,QAAQ,KAAK,EAAE,CAAC,IAAI,CAAC;AACrB,QAAQ,QAAQ,EAAE,CAAC,OAAO,CAAC;AAC3B,QAAQ,cAAc,EAAE,OAAO,CAAC,IAAI;AACpC,OAAO,CAAC,CAAC;AACT,KAAK,MAAM;AACX,MAAM,EAAE,CAAC,eAAe,EAAE,CAAC;AAC3B,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd,GAAG;AACH,EAAE,6BAA6B,CAAC,cAAc,EAAE;AAChD,IAAI,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;AAClD,IAAI,OAAO,EAAE,CAAC,aAAa,CAACC,oBAAS,CAAC,CAAC;AACvC,GAAG;AACH,EAAE,gBAAgB,CAAC,cAAc,EAAE;AACnC,IAAI,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;AAClD,IAAI,OAAO,IAAIC,kBAAO,CAAC,EAAE,CAAC,CAAC;AAC3B,GAAG;AACH,EAAE,sBAAsB,CAAC,cAAc,EAAE;AACzC,IAAI,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;AAClD,IAAI,OAAO,EAAE,CAAC,aAAa,CAACC,2BAAgB,CAAC,CAAC;AAC9C,GAAG;AACH;;AChDO,MAAM,8BAA8B,CAAC;AAC5C,EAAE,MAAM,8BAA8B,CAAC,cAAc,EAAE,WAAW,EAAE;AACpE,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,MAAM,2BAA2B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;AAC1E,IAAI,MAAM,SAAS,GAAG,CAAC,EAAE,GAAG,WAAW,CAAC,IAAI,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;AAC3E,IAAI,IAAI,SAAS,EAAE;AACnB,MAAM,2BAA2B,CAAC,mBAAmB,GAAG,SAAS,CAAC;AAClE,KAAK,MAAM;AACX,MAAM,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;AAClF,KAAK;AACL,IAAI,OAAO,2BAA2B,CAAC;AACvC,GAAG;AACH;;ACZO,MAAM,sCAAsC,CAAC;AACpD,EAAE,MAAM,8BAA8B,CAAC,cAAc,EAAE,YAAY,EAAE;AACrE,IAAI,OAAO,cAAc,CAAC;AAC1B,GAAG;AACH;;ACFO,MAAM,8BAA8B,CAAC;AAC5C,EAAE,WAAW,GAAG;AAChB,IAAI,IAAI,CAAC,iBAAiB,GAAG,YAAY;AACzC,MAAM,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK;AAC9C,QAAQC,uBAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,KAAK;AAC3C,UAAU,IAAI,GAAG,EAAE;AACnB,YAAY,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AAC/B,WAAW;AACX,UAAU,OAAO,OAAO,CAACA,uBAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACjD,SAAS,CAAC,CAAC;AACX,OAAO,CAAC,CAAC;AACT,KAAK,CAAC;AACN,GAAG;AACH,EAAE,gBAAgB,CAAC,KAAK,EAAE;AAC1B,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,WAAW,MAAM,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC;AAC5G,GAAG;AACH,EAAE,MAAM,cAAc,CAAC,UAAU,EAAE,UAAU,EAAE;AAC/C,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,OAAO,EAAE,MAAM,KAAK;AAClD,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;AACtD,MAAM,IAAI,EAAE,QAAQ,YAAYC,eAAW,CAAC;AAC5C,QAAQ,OAAO,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;AAC1D,MAAM,IAAI,KAAK,GAAG;AAClB,QAAQ,WAAW,EAAE,QAAQ,CAAC,WAAW;AACzC,QAAQ,eAAe,EAAE,QAAQ,CAAC,eAAe;AACjD,QAAQ,YAAY,EAAE,QAAQ,CAAC,YAAY;AAC3C,OAAO,CAAC;AACR,MAAM,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;AACvC,QAAQ,OAAO,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;AAC/D,MAAM,IAAI,CAAC,UAAU;AACrB,QAAQ,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9B,MAAM,IAAI;AACV,QAAQ,MAAM,MAAM,GAAG;AACvB,UAAU,OAAO,EAAE,UAAU;AAC7B,UAAU,eAAe,EAAE,iBAAiB;AAC5C,SAAS,CAAC;AACV,QAAQ,IAAI,UAAU;AACtB,UAAU,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;AACzC,QAAQ,MAAM,WAAW,GAAG,MAAM,IAAID,uBAAG,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;AAC7E,QAAQ,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE;AACtC,UAAU,MAAM,IAAI,KAAK,CAAC,CAAC,iCAAiC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;AAC5E,SAAS;AACT,QAAQ,KAAK,GAAG;AAChB,UAAU,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,WAAW;AAC1D,UAAU,eAAe,EAAE,WAAW,CAAC,WAAW,CAAC,eAAe;AAClE,UAAU,YAAY,EAAE,WAAW,CAAC,WAAW,CAAC,YAAY;AAC5D,SAAS,CAAC;AACV,OAAO,CAAC,OAAO,CAAC,EAAE;AAClB,QAAQ,OAAO,CAAC,IAAI,CAAC,CAAC,sCAAsC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,QAAQ,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,OAAO;AACP,MAAM,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AAC5B,KAAK,CAAC,CAAC;AACP,GAAG;AACH,EAAE,MAAM,cAAc,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE;AAC5D,IAAI,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAC1E,IAAI,MAAM,OAAO,GAAG;AACpB,MAAM,IAAI,EAAE,CAAC,iBAAiB,CAAC;AAC/B,MAAM,IAAI,EAAE,CAAC,8DAA8D,CAAC;AAC5E,MAAM,OAAO,EAAE;AACf,QAAQ,cAAc,EAAE,WAAW;AACnC,OAAO;AACP,MAAM,SAAS,EAAE,IAAI;AACrB,KAAK,CAAC;AACN,IAAI,MAAM,MAAM,GAAGE,SAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC9C,IAAI,MAAM,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACvD,IAAI,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACpE,IAAI,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAClG,IAAI,OAAO,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAC5C,GAAG;AACH,EAAE,MAAM,8BAA8B,CAAC,cAAc,EAAE;AACvD,IAAI,MAAM,2BAA2B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;AAC1E,IAAI,2BAA2B,CAAC,mBAAmB,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;AAC3J,IAAI,OAAO,2BAA2B,CAAC;AACvC,GAAG;AACH;;AC3EO,MAAM,kCAAkC,CAAC;AAChD,EAAE,MAAM,8BAA8B,CAAC,cAAc,EAAE;AACvD,IAAI,MAAM,2BAA2B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;AAC1E,IAAI,MAAM,MAAM,GAAG,IAAIR,oBAAS,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC;AAC3D,IAAI,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;AAC3D,IAAI,IAAI,WAAW,EAAE;AACrB,MAAM,2BAA2B,CAAC,mBAAmB,GAAG,WAAW,CAAC;AACpE,KAAK,MAAM;AACX,MAAM,MAAM,IAAI,KAAK,CAAC,sFAAsF,CAAC,CAAC;AAC9G,KAAK;AACL,IAAI,OAAO,2BAA2B,CAAC;AACvC,GAAG;AACH;;ACVA,MAAM,QAAQ,GAAG,+CAA+C,CAAC;AAC1D,MAAM,qCAAqC,CAAC;AACnD,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,IAAIS,+BAAsB,EAAE,EAAE;AACtE,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;AACzB,IAAI,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;AAC3C,IAAI,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC;AAC5D,GAAG;AACH,EAAE,MAAM,8BAA8B,CAAC,cAAc,EAAE;AACvD,IAAI,MAAM,2BAA2B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;AAC1E,IAAI,2BAA2B,CAAC,mBAAmB,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC5E,IAAI,OAAO,2BAA2B,CAAC;AACvC,GAAG;AACH,EAAE,MAAM,QAAQ,GAAG;AACnB,IAAI,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE;AACtC,MAAM,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AACpC,KAAK;AACL,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;AAC/B,MAAM,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;AAClD,KAAK;AACL,IAAI,OAAO,IAAI,CAAC,eAAe,CAAC;AAChC,GAAG;AACH,EAAE,MAAM,aAAa,GAAG;AACxB,IAAI,IAAI;AACR,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;AAC3D,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,QAAQ,EAAE;AAC3E,QAAQ,cAAc,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE;AACxC,OAAO,CAAC,CAAC;AACT,MAAM,IAAI,CAAC,cAAc,EAAE;AAC3B,QAAQ,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAC/C,OAAO;AACP,MAAM,IAAI,CAAC,WAAW,GAAG,cAAc,CAAC;AACxC,KAAK,CAAC,OAAO,GAAG,EAAE;AAClB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;AAC5D,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;AAC/B,QAAQ,MAAM,GAAG,CAAC;AAClB,OAAO;AACP,KAAK;AACL,IAAI,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,CAAC;AAClC,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAClC,GAAG;AACH,EAAE,oBAAoB,GAAG;AACzB,IAAI,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,kBAAkB,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;AAC1E,IAAI,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,SAAS,CAAC;AACnC,GAAG;AACH,EAAE,YAAY,GAAG;AACjB,IAAI,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC;AAC7D,GAAG;AACH;;AClDO,MAAM,4BAA4B,CAAC;AAC1C,EAAE,MAAM,8BAA8B,CAAC,cAAc,EAAE,WAAW,EAAE;AACpE,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC;AACf,IAAI,MAAM,2BAA2B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;AAC1E,IAAI,MAAM,EAAE,iBAAiB,EAAE,GAAG,cAAc,CAAC;AACjD,IAAI,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,KAAK,EAAE,EAAE;AACxD,MAAM,MAAM,IAAI,KAAK,CAAC,CAAC,yDAAyD,CAAC,CAAC,CAAC;AACnF,KAAK;AACL,IAAI,MAAM,SAAS,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,WAAW,CAAC,IAAI,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC;AACzH,IAAI,IAAI,SAAS,EAAE;AACnB,MAAM,2BAA2B,CAAC,mBAAmB,GAAG,SAAS,CAAC;AAClE,KAAK,MAAM;AACX,MAAM,MAAM,IAAI,KAAK,CAAC,CAAC,gCAAgC,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC9F,KAAK;AACL,IAAI,OAAO,2BAA2B,CAAC;AACvC,GAAG;AACH;;ACVO,MAAM,iCAAiC,CAAC;AAC/C,EAAE,OAAO,mCAAmC,CAAC,YAAY,EAAE,OAAO,EAAE;AACpE,IAAI,QAAQ,YAAY;AACxB,MAAM,KAAK,QAAQ,EAAE;AACrB,QAAQ,OAAO,IAAI,8BAA8B,EAAE,CAAC;AACpD,OAAO;AACP,MAAM,KAAK,KAAK,EAAE;AAClB,QAAQ,OAAO,IAAI,8BAA8B,EAAE,CAAC;AACpD,OAAO;AACP,MAAM,KAAK,OAAO,EAAE;AACpB,QAAQ,OAAO,IAAI,qCAAqC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACzE,OAAO;AACP,MAAM,KAAK,gBAAgB,EAAE;AAC7B,QAAQ,OAAO,IAAI,sCAAsC,EAAE,CAAC;AAC5D,OAAO;AACP,MAAM,KAAK,sBAAsB,EAAE;AACnC,QAAQ,OAAO,IAAI,kCAAkC,EAAE,CAAC;AACxD,OAAO;AACP,MAAM,KAAK,MAAM,EAAE;AACnB,QAAQ,OAAO,IAAI,4BAA4B,EAAE,CAAC;AAClD,OAAO;AACP,MAAM,SAAS;AACf,QAAQ,MAAM,IAAI,KAAK,CAAC,CAAC,cAAc,EAAE,YAAY,CAAC,oDAAoD,CAAC,CAAC,CAAC;AAC7G,OAAO;AACP,KAAK;AACL,GAAG;AACH;;AC/BY,MAAC,eAAe,GAAG;AAC/B,EAAE;AACF,IAAI,KAAK,EAAE,EAAE;AACb,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,MAAM;AAClB,IAAI,UAAU,EAAE,MAAM;AACtB,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,EAAE;AACb,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,UAAU;AACtB,IAAI,UAAU,EAAE,UAAU;AAC1B,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,EAAE;AACb,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,YAAY;AACxB,IAAI,UAAU,EAAE,YAAY;AAC5B,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,MAAM;AACjB,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,aAAa;AACzB,IAAI,UAAU,EAAE,aAAa;AAC7B,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,MAAM;AACjB,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,aAAa;AACzB,IAAI,UAAU,EAAE,aAAa;AAC7B,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,aAAa;AACxB,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,0BAA0B;AACtC,IAAI,UAAU,EAAE,0BAA0B;AAC1C,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,OAAO;AAClB,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,MAAM;AAClB,IAAI,UAAU,EAAE,MAAM;AACtB,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,OAAO;AAClB,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,UAAU;AACtB,IAAI,UAAU,EAAE,UAAU;AAC1B,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,mBAAmB;AAC9B,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,WAAW;AACvB,IAAI,UAAU,EAAE,WAAW;AAC3B,GAAG;AACH,EAAE;AACF,IAAI,KAAK,EAAE,MAAM;AACjB,IAAI,UAAU,EAAE,IAAI;AACpB,IAAI,MAAM,EAAE,cAAc;AAC1B,IAAI,UAAU,EAAE,cAAc;AAC9B,GAAG;AACH,EAAE;AACF,MAAM,kBAAkB,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC;AACtD,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,GAAG,KAAK,KAAK,CAAC,CAAC;AACzC,MAAM,8BAA8B,GAAG,CAAC,KAAK,KAAK;AAClD,EAAE,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC;AAC9D,CAAC,CAAC;AACF,MAAM,oBAAoB,GAAG,CAAC,OAAO,KAAK;AAC1C,EAAE,OAAO;AACT,IAAI,YAAY,EAAE,8BAA8B,CAAC,OAAO,CAAC,YAAY,CAAC;AACtE,IAAI,YAAY,EAAE,8BAA8B,CAAC,OAAO,CAAC,YAAY,CAAC;AACtE,IAAI,UAAU,EAAE,8BAA8B,CAAC,OAAO,CAAC,UAAU,CAAC;AAClE,GAAG,CAAC;AACJ,CAAC,CAAC;AACF,MAAM,qBAAqB,GAAG,CAAC,SAAS,KAAK;AAC7C,EAAE,OAAO;AACT,IAAI,SAAS,EAAE,SAAS,CAAC,SAAS;AAClC,IAAI,QAAQ,EAAE,oBAAoB,CAAC,SAAS,CAAC,QAAQ,CAAC;AACtD,IAAI,WAAW,EAAE,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC;AAC5D,GAAG,CAAC;AACJ,CAAC,CAAC;AACF,MAAM,sBAAsB,GAAG,CAAC,UAAU,KAAK;AAC/C,EAAE,OAAO,UAAU,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK;AACvC,IAAI,OAAO;AACX,MAAM,GAAG,EAAE,EAAE,CAAC,GAAG;AACjB,MAAM,MAAM,EAAE,oBAAoB,CAAC,EAAE,CAAC,MAAM,CAAC;AAC7C,MAAM,GAAG,EAAE,oBAAoB,CAAC,EAAE,CAAC,GAAG,CAAC;AACvC,MAAM,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,qBAAqB,CAAC;AAC1D,KAAK,CAAC;AACN,GAAG,CAAC,CAAC;AACL,CAAC,CAAC;AACK,MAAM,uBAAuB,CAAC;AACrC,EAAE,WAAW,CAAC;AACd,IAAI,MAAM;AACV,IAAI,OAAO;AACX,IAAI,cAAc;AAClB,IAAI,eAAe;AACnB,IAAI,kBAAkB,GAAG,eAAe;AACxC,GAAG,EAAE;AACL,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;AACzB,IAAI,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC3B,IAAI,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;AACzC,IAAI,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;AAC3C,IAAI,IAAI,CAAC,kBAAkB,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAC1D,IAAI,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;AAC9B,GAAG;AACH,EAAE,MAAM,4BAA4B,CAAC,WAAW,EAAE;AAClD,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AACnD,IAAI,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,WAAW,CAAC,MAAM,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,4BAA4B,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,WAAW,CAAC,MAAM,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACtR,IAAI,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC;AACxF,IAAI,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK;AAChD,MAAM,OAAO,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,8BAA8B,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AACrG,KAAK,CAAC,CAAC;AACP,IAAI,MAAM,8BAA8B,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvE,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,qBAAqB,EAAE,UAAU,CAAC,iBAAiB,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5I,IAAI,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,WAAW,CAAC,MAAM,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,wCAAwC,CAAC,KAAK,CAAC,2BAA2B,EAAE,UAAU,CAAC,CAAC,CAAC;AACnP,IAAI,MAAM,SAAS,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,WAAW,CAAC,MAAM,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,QAAQ,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,mCAAmC,CAAC,CAAC;AAC1L,IAAI,OAAO,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,GAAG,CAAC,CAAC,kBAAkB,KAAK;AAClF,MAAM,OAAO,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC;AACjD,QAAQ,SAAS,EAAE,UAAU;AAC7B,QAAQ,cAAc,EAAE,kBAAkB;AAC1C,QAAQ,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;AACnD,QAAQ,aAAa;AACrB,QAAQ,eAAe,EAAE,IAAI,CAAC,eAAe;AAC7C,QAAQ,SAAS;AACjB,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,CAAC;AACxI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AAC7C,GAAG;AACH,EAAE,yBAAyB,CAAC,cAAc,EAAE;AAC5C,IAAI,OAAO;AACX,MAAM,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;AACnN,KAAK,CAAC;AACN,GAAG;AACH,EAAE,gBAAgB,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;AACtD,IAAI,MAAM,OAAO,GAAG;AACpB,MAAM,OAAO,EAAE;AACf,QAAQ,IAAI,EAAE,cAAc,CAAC,IAAI;AACjC,OAAO;AACP,MAAM,UAAU,EAAE,sBAAsB,CAAC,OAAO,CAAC;AACjD,MAAM,SAAS,EAAE,MAAM,CAAC,SAAS;AACjC,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM;AAC3B,KAAK,CAAC;AACN,IAAI,IAAI,cAAc,CAAC,YAAY,EAAE;AACrC,MAAM,OAAO,CAAC,OAAO,CAAC,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC;AACjE,KAAK;AACL,IAAI,IAAI,cAAc,CAAC,YAAY,EAAE;AACrC,MAAM,OAAO,CAAC,OAAO,CAAC,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC;AACjE,KAAK;AACL,IAAI,IAAI,cAAc,CAAC,mBAAmB,EAAE;AAC5C,MAAM,OAAO,CAAC,OAAO,CAAC,mBAAmB,GAAG,cAAc,CAAC,mBAAmB,CAAC;AAC/E,KAAK;AACL,IAAI,OAAO,OAAO,CAAC;AACnB,GAAG;AACH,EAAE,MAAM,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE;AAClD,IAAI,IAAI,cAAc,CAAC,iBAAiB,EAAE;AAC1C,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC1B,KAAK;AACL,IAAI,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK;AAClH,MAAM,IAAI,EAAE,CAAC;AACb,MAAM,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;AAC/D,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AACzB,IAAI,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC,0BAA0B,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;AACvH,IAAI,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC1D,GAAG;AACH,EAAE,iBAAiB,CAAC,QAAQ,EAAE;AAC9B,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE;AACxC,MAAM,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;AAC5C,KAAK;AACL,IAAI,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,iCAAiC,CAAC,mCAAmC,CAAC,QAAQ,EAAE;AACrH,MAAM,MAAM,EAAE,IAAI,CAAC,MAAM;AACzB,KAAK,CAAC,CAAC;AACP,IAAI,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;AAC1C,GAAG;AACH;;AC5KA,MAAM,OAAO,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;AACvD,SAAS,6BAA6B,CAAC,OAAO,EAAE;AAChD,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACb,EAAE,MAAM,OAAO,GAAGC,0BAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,KAAK;AACrD,IAAI,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,QAAQ,GAAG,WAAW,CAAC;AACnD,GAAG,CAAC,CAAC;AACL,EAAE,OAAO;AACT,IAAI,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE;AACnD,IAAI,SAAS,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,SAAS,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE;AACzD,GAAG,CAAC;AACJ,CAAC;AACD,MAAM,qBAAqB,GAAG,CAAC,UAAU,KAAK;AAC9C,EAAE,QAAQ,UAAU;AACpB,IAAI,KAAK,GAAG;AACZ,MAAM,OAAO,aAAa,CAAC;AAC3B,IAAI,KAAK,GAAG;AACZ,MAAM,OAAO,oBAAoB,CAAC;AAClC,IAAI,KAAK,GAAG;AACZ,MAAM,OAAO,cAAc,CAAC;AAC5B,IAAI;AACJ,MAAM,OAAO,eAAe,CAAC;AAC7B,GAAG;AACH,CAAC,CAAC;AACK,MAAM,4BAA4B,CAAC;AAC1C,EAAE,WAAW,CAAC;AACd,IAAI,wBAAwB;AAC5B,IAAI,MAAM;AACV,GAAG,EAAE;AACL,IAAI,IAAI,CAAC,wBAAwB,GAAG,wBAAwB,CAAC;AAC7D,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;AACzB,GAAG;AACH,EAAE,sBAAsB,CAAC,MAAM,EAAE;AACjC,IAAI,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,KAAK;AAC/G,MAAM,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,aAAa,IAAI,CAAC,2BAA2B,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5O,KAAK,CAAC,CAAC;AACP,IAAI,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;AACzE,GAAG;AACH,EAAE,0BAA0B,CAAC,cAAc,EAAE,SAAS,EAAE;AACxD,IAAI,MAAM,aAAa,GAAG,IAAI,CAAC,wBAAwB,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;AACzF,IAAI,MAAM,OAAO,GAAG,IAAI,CAAC,wBAAwB,CAAC,6BAA6B,CAAC,cAAc,CAAC,CAAC;AAChG,IAAI,OAAOC,kBAAO,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;AACtD,GAAG;AACH,EAAE,oCAAoC,CAAC,CAAC,EAAE;AAC1C,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE;AAC7C,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxJ,MAAM,OAAO;AACb,QAAQ,SAAS,EAAE,qBAAqB,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;AAC/D,QAAQ,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;AACzC,QAAQ,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ;AACrD,OAAO,CAAC;AACR,KAAK;AACL,IAAI,MAAM,CAAC,CAAC;AACZ,GAAG;AACH,EAAE,aAAa,CAAC,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE;AAChF,IAAI,MAAM,aAAa,GAAG,IAAI,CAAC,wBAAwB,CAAC,sBAAsB,CAAC,cAAc,CAAC,CAAC;AAC/F,IAAI,aAAa,CAAC,cAAc,CAAC,CAAC,cAAc,KAAK;AACrD,MAAM,cAAc,CAAC,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;AAChF,KAAK,CAAC,CAAC;AACP,IAAI,IAAI,SAAS,EAAE;AACnB,MAAM,OAAO,aAAa,CAAC,0BAA0B,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;AACrK,QAAQ,OAAO;AACf,UAAU,IAAI,EAAE,UAAU;AAC1B,UAAU,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;AACjC,SAAS,CAAC;AACV,OAAO,CAAC,CAAC;AACT,KAAK;AACL,IAAI,OAAO,aAAa,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;AACrJ,MAAM,OAAO;AACb,QAAQ,IAAI,EAAE,UAAU;AACxB,QAAQ,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;AAC/B,OAAO,CAAC;AACR,KAAK,CAAC,CAAC;AACP,GAAG;AACH;;AChEO,MAAM,iBAAiB,CAAC;AAC/B,EAAE,WAAW,CAAC,GAAG,EAAE;AACnB,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;AACnB,IAAI,IAAI,CAAC,6BAA6B,GAAGC,cAAQ,CAAC,UAAU,CAAC;AAC7D,MAAM,OAAO,EAAE,EAAE;AACjB,KAAK,CAAC,CAAC;AACP,GAAG;AACH,EAAE,OAAO,aAAa,CAAC,GAAG,EAAE;AAC5B,IAAI,OAAO,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;AACtC,GAAG;AACH,EAAE,MAAM,KAAK,GAAG;AAChB,IAAI,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AACvB,IAAI,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AACnC,IAAI,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AACnC,IAAI,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;AACnD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE;AACnC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;AAClD,QAAQ,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;AAC/D,OAAO;AACP,MAAM,MAAM,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;AAC3F,MAAM,OAAO;AACb,QAAQ,MAAM,EAAEC,0BAAM,EAAE;AACxB,OAAO,CAAC;AACR,KAAK;AACL,IAAI,MAAM,eAAe,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;AACxD,IAAI,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,KAAK,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;AAC3E,IAAI,MAAM,eAAe,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,eAAe,KAAK,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;AACrI,IAAI,MAAM,cAAc,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,cAAc,KAAK,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,eAAe,CAAC,CAAC;AAC/I,IAAI,MAAM,eAAe,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,eAAe,KAAK,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,oBAAoB,CAAC;AACjG,MAAM,MAAM;AACZ,MAAM,OAAO;AACb,MAAM,cAAc;AACpB,MAAM,eAAe;AACrB,MAAM,kBAAkB,EAAE,IAAI,CAAC,qBAAqB,EAAE;AACtD,KAAK,CAAC,CAAC;AACP,IAAI,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;AACtE,IAAI,OAAO;AACX,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,OAAO;AACb,MAAM,eAAe;AACrB,MAAM,MAAM;AACZ,MAAM,cAAc;AACpB,KAAK,CAAC;AACN,GAAG;AACH,EAAE,kBAAkB,CAAC,eAAe,EAAE;AACtC,IAAI,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;AAC3C,IAAI,OAAO,IAAI,CAAC;AAChB,GAAG;AACH,EAAE,gCAAgC,CAAC,eAAe,EAAE;AACpD,IAAI,IAAI,CAAC,6BAA6B,GAAG,eAAe,CAAC;AACzD,IAAI,OAAO,IAAI,CAAC;AAChB,GAAG;AACH,EAAE,kBAAkB,CAAC,eAAe,EAAE;AACtC,IAAI,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;AAC3C,IAAI,OAAO,IAAI,CAAC;AAChB,GAAG;AACH,EAAE,UAAU,CAAC,OAAO,EAAE;AACtB,IAAI,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC3B,IAAI,OAAO,IAAI,CAAC;AAChB,GAAG;AACH,EAAE,iBAAiB,CAAC,cAAc,EAAE;AACpC,IAAI,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;AACzC,IAAI,OAAO,IAAI,CAAC;AAChB,GAAG;AACH,EAAE,oBAAoB,GAAG;AACzB,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,4BAA4B,CAAC,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM;AACxI,MAAM,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC;AACjC,MAAM,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC;AAC3C,MAAM,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC;AACnC,MAAM,UAAU,EAAE,iBAAiB;AACnC,KAAK,CAAC,CAAC,CAAC;AACR,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,mDAAmD,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACzG,IAAI,OAAO,eAAe,CAAC;AAC3B,GAAG;AACH,EAAE,oBAAoB,CAAC,eAAe,EAAE;AACxC,IAAI,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AACnC,IAAI,OAAO,0BAA0B,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAC/D,GAAG;AACH,EAAE,oBAAoB,CAAC,OAAO,EAAE;AAChC,IAAI,OAAO,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAChD,GAAG;AACH,EAAE,YAAY,GAAG;AACjB,IAAI,OAAO,IAAI,4BAA4B,CAAC;AAC5C,MAAM,wBAAwB,EAAE,IAAI,wBAAwB,EAAE;AAC9D,MAAM,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM;AAC7B,KAAK,CAAC,CAAC;AACP,GAAG;AACH,EAAE,mBAAmB,CAAC,MAAM,EAAE,eAAe,EAAE;AAC/C,IAAI,QAAQ,MAAM;AAClB,MAAM,KAAK,aAAa;AACxB,QAAQ,OAAO,IAAI,CAAC,8BAA8B,CAAC,eAAe,CAAC,CAAC;AACpE,MAAM,KAAK,MAAM;AACjB,QAAQ,OAAO,IAAI,CAAC,uBAAuB,CAAC,eAAe,CAAC,CAAC;AAC7D,MAAM;AACN,QAAQ,MAAM,IAAI,KAAK,CAAC,CAAC,6CAA6C,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACnF,KAAK;AACL,GAAG;AACH,EAAE,8BAA8B,CAAC,eAAe,EAAE;AAClD,IAAI,OAAO,IAAI,yBAAyB,CAAC,eAAe,CAAC,CAAC;AAC1D,GAAG;AACH,EAAE,uBAAuB,CAAC,gBAAgB,EAAE;AAC5C,IAAI,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACvC,GAAG;AACH,EAAE,WAAW,CAAC,eAAe,EAAE,eAAe,EAAE;AAChD,IAAI,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AACnC,IAAI,MAAM,MAAM,GAAGA,0BAAM,EAAE,CAAC;AAC5B,IAAI,MAAM,CAAC,GAAG,CAACC,2BAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAC/B,IAAI,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,EAAE,GAAG,KAAK;AAC5D,MAAM,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC;AAC7C,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC;AACnC,MAAM,IAAI;AACV,QAAQ,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,4BAA4B,CAAC,WAAW,CAAC,CAAC;AACzF,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC3B,OAAO,CAAC,OAAO,CAAC,EAAE;AAClB,QAAQ,MAAM,CAAC,KAAK,CAAC,CAAC,0CAA0C,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3F,QAAQ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AACnD,OAAO;AACP,KAAK,CAAC,CAAC;AACP,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK;AAC9C,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC;AAC7E,MAAM,GAAG,CAAC,IAAI,CAAC;AACf,QAAQ,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM;AAC3C,UAAU,IAAI,EAAE,EAAE,CAAC,IAAI;AACvB,UAAU,YAAY,EAAE,EAAE,CAAC,YAAY;AACvC,UAAU,YAAY,EAAE,EAAE,CAAC,YAAY;AACvC,UAAU,iBAAiB,EAAE,EAAE,CAAC,iBAAiB;AACjD,SAAS,CAAC,CAAC;AACX,OAAO,CAAC,CAAC;AACT,KAAK,CAAC,CAAC;AACP,IAAI,OAAO,MAAM,CAAC;AAClB,GAAG;AACH,EAAE,MAAM,mBAAmB,CAAC,eAAe,EAAE;AAC7C,IAAI,MAAM,cAAc,GAAG,MAAM,eAAe,CAAC,WAAW,EAAE,CAAC;AAC/D,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,8CAA8C,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACnG,IAAI,OAAO,cAAc,CAAC;AAC1B,GAAG;AACH,EAAE,uBAAuB,GAAG;AAC5B,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC;AAC7E,GAAG;AACH,EAAE,qBAAqB,GAAG;AAC1B,IAAI,MAAM,yBAAyB,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,wBAAwB,CAAC,CAAC;AACvG,IAAI,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,gCAAgC,CAAC,CAAC;AACpG,IAAI,IAAI,kBAAkB,CAAC;AAC3B,IAAI,IAAI,yBAAyB,EAAE;AACnC,MAAM,kBAAkB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,yBAAyB,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;AAC/G,KAAK;AACL,IAAI,IAAI,mBAAmB,EAAE;AAC7B,MAAM,kBAAkB,GAAG,kBAAkB,IAAI,IAAI,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAC7F,MAAM,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE;AAC5C,QAAQ,IAAI,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;AACrD,UAAU,GAAG,CAAC,UAAU,GAAG,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACzE,SAAS;AACT,OAAO;AACP,KAAK;AACL,IAAI,OAAO,kBAAkB,CAAC;AAC9B,GAAG;AACH;;ACxKO,eAAe,YAAY,CAAC,OAAO,EAAE;AAC5C,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,iBAAiB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE,CAAC;AACxH,EAAE,OAAO,MAAM,CAAC;AAChB;;;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ interface ObjectToFetch {
|
|
|
31
31
|
interface CustomResource extends ObjectToFetch {
|
|
32
32
|
objectType: 'customresources';
|
|
33
33
|
}
|
|
34
|
-
declare type KubernetesObjectTypes = 'pods' | 'services' | 'configmaps' | 'deployments' | 'replicasets' | 'horizontalpodautoscalers' | 'jobs' | 'cronjobs' | 'ingresses' | 'customresources';
|
|
34
|
+
declare type KubernetesObjectTypes = 'pods' | 'services' | 'configmaps' | 'deployments' | 'replicasets' | 'horizontalpodautoscalers' | 'jobs' | 'cronjobs' | 'ingresses' | 'customresources' | 'statefulsets';
|
|
35
35
|
interface KubernetesClustersSupplier {
|
|
36
36
|
/**
|
|
37
37
|
* Returns the cached list of clusters.
|
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.
|
|
4
|
+
"version": "0.6.0-next.2",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@azure/identity": "^2.0.4",
|
|
39
|
-
"@backstage/backend-common": "^0.
|
|
40
|
-
"@backstage/catalog-model": "^1.0.
|
|
39
|
+
"@backstage/backend-common": "^0.14.0-next.2",
|
|
40
|
+
"@backstage/catalog-model": "^1.0.3-next.0",
|
|
41
41
|
"@backstage/config": "^1.0.1",
|
|
42
42
|
"@backstage/errors": "^1.0.0",
|
|
43
|
-
"@backstage/plugin-kubernetes-common": "^0.
|
|
43
|
+
"@backstage/plugin-kubernetes-common": "^0.3.0-next.1",
|
|
44
44
|
"@google-cloud/container": "^3.0.0",
|
|
45
45
|
"@kubernetes/client-node": "^0.16.0",
|
|
46
46
|
"@types/express": "^4.17.6",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"yn": "^4.0.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@backstage/cli": "^0.17.
|
|
64
|
+
"@backstage/cli": "^0.17.2-next.2",
|
|
65
65
|
"@types/aws4": "^1.5.1",
|
|
66
66
|
"aws-sdk-mock": "^5.2.1",
|
|
67
67
|
"supertest": "^6.1.3"
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"dist",
|
|
71
71
|
"schema.d.ts"
|
|
72
72
|
],
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "afc672d59763a835574e6c47819107d22cfd1ad7"
|
|
74
74
|
}
|