@backstage/plugin-kubernetes-backend 0.9.3-next.2 → 0.9.4-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +37 -37
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @backstage/plugin-kubernetes-backend
|
|
2
2
|
|
|
3
|
+
## 0.9.4-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/catalog-client@1.4.0-next.0
|
|
9
|
+
- @backstage/backend-common@0.18.3-next.0
|
|
10
|
+
- @backstage/catalog-model@1.2.1-next.0
|
|
11
|
+
- @backstage/config@1.0.6
|
|
12
|
+
- @backstage/errors@1.1.4
|
|
13
|
+
- @backstage/plugin-auth-node@0.2.12-next.0
|
|
14
|
+
- @backstage/plugin-kubernetes-common@0.6.1-next.0
|
|
15
|
+
|
|
16
|
+
## 0.9.3
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 2518ef5b8a: Adding new Cluster detail fields to catalogClusterLocator. Replace deprecated imports with k8s annotations from plugin-kubernetes-common.
|
|
21
|
+
- 7ff81f7692: Kubernetes proxy endpoint now accepts content types that are not json
|
|
22
|
+
- 5b7cd5580d: Moving the backend-test-utils to devDependencies.
|
|
23
|
+
- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`.
|
|
24
|
+
- a53d06afe5: The name of the header used to specify a cluster to the proxy endpoint is now visible in the API reference.
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
- @backstage/plugin-kubernetes-common@0.6.0
|
|
27
|
+
- @backstage/backend-common@0.18.2
|
|
28
|
+
- @backstage/catalog-model@1.2.0
|
|
29
|
+
- @backstage/catalog-client@1.3.1
|
|
30
|
+
- @backstage/config@1.0.6
|
|
31
|
+
- @backstage/errors@1.1.4
|
|
32
|
+
- @backstage/plugin-auth-node@0.2.11
|
|
33
|
+
|
|
3
34
|
## 0.9.3-next.2
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/CatalogClusterLocator.ts","../src/cluster-locator/LocalKubectlProxyLocator.ts","../src/cluster-locator/index.ts","../src/routes/resourcesRoutes.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesProxy.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\n/**\n *\n * @alpha\n */\nexport type SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\n/**\n *\n * @alpha\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 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\n/**\n *\n * @alpha\n */\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @alpha\n */\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = authConfig.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\n/**\n *\n * @alpha\n */\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\n\n/**\n *\n * @alpha\n */\nexport class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @alpha\n */\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined = authConfig.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { NoopKubernetesAuthTranslator } from './NoopKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\n/**\n *\n * @alpha\n */\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n options: {\n logger: Logger;\n },\n ): KubernetesAuthTranslator {\n switch (authProvider) {\n case 'google': {\n return new GoogleKubernetesAuthTranslator();\n }\n case 'aws': {\n return new AwsIamKubernetesAuthTranslator();\n }\n case 'azure': {\n return new AzureIdentityKubernetesAuthTranslator(options.logger);\n }\n case 'serviceAccount': {\n return new NoopKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n case 'localKubectlProxy': {\n return new NoopKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\n }\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n caFile: c.getOptionalString('caFile'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\n );\n }\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { CATALOG_FILTER_EXISTS, CatalogApi } from '@backstage/catalog-client';\nimport {\n ANNOTATION_KUBERNETES_API_SERVER,\n ANNOTATION_KUBERNETES_API_SERVER_CA,\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP,\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY,\n ANNOTATION_KUBERNETES_DASHBOARD_URL,\n ANNOTATION_KUBERNETES_DASHBOARD_APP,\n} from '@backstage/plugin-kubernetes-common';\n\nexport class CatalogClusterLocator implements KubernetesClustersSupplier {\n private catalogClient: CatalogApi;\n\n constructor(catalogClient: CatalogApi) {\n this.catalogClient = catalogClient;\n }\n\n static fromConfig(catalogApi: CatalogApi): CatalogClusterLocator {\n return new CatalogClusterLocator(catalogApi);\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n const apiServerKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER}`;\n const apiServerCaKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER_CA}`;\n const authProviderKey = `metadata.annotations.${ANNOTATION_KUBERNETES_AUTH_PROVIDER}`;\n\n const filter: Record<string, symbol | string> = {\n kind: 'Resource',\n 'spec.type': 'kubernetes-cluster',\n [apiServerKey]: CATALOG_FILTER_EXISTS,\n [apiServerCaKey]: CATALOG_FILTER_EXISTS,\n [authProviderKey]: CATALOG_FILTER_EXISTS,\n };\n\n const clusters = await this.catalogClient.getEntities({\n filter: [filter],\n });\n return clusters.items.map(entity => {\n const clusterDetails: ClusterDetails = {\n name: entity.metadata.name,\n url: entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER]!,\n caData:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER_CA]!,\n authProvider:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_AUTH_PROVIDER]!,\n oidcTokenProvider:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER\n ]!,\n skipMetricsLookup:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP\n ]! === 'true'\n ? true\n : false,\n skipTLSVerify:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY\n ]! === 'true'\n ? true\n : false,\n dashboardUrl:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_URL]!,\n dashboardApp:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_APP]!,\n };\n\n return clusterDetails;\n });\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class LocalKubectlProxyClusterLocator\n implements KubernetesClustersSupplier\n{\n private readonly clusterDetails: ClusterDetails[];\n\n public constructor() {\n this.clusterDetails = [\n {\n name: 'local',\n url: 'http:/localhost:8001',\n authProvider: 'localKubectlProxy',\n skipMetricsLookup: true,\n },\n ];\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\nimport { CatalogClusterLocator } from './CatalogClusterLocator';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { LocalKubectlProxyClusterLocator } from './LocalKubectlProxyLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n catalogClient: CatalogApi,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'catalog':\n return CatalogClusterLocator.fromConfig(catalogClient);\n case 'localKubectlProxy':\n return new LocalKubectlProxyClusterLocator();\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\n};\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n CompoundEntityRef,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { InputError, AuthenticationError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '../types/types';\nimport { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalogApi: CatalogApi,\n objectsProvider: KubernetesObjectsProvider,\n) => {\n const getEntityByReq = async (req: Request<any>) => {\n const rawEntityRef = req.body.entityRef;\n if (rawEntityRef && typeof rawEntityRef !== 'string') {\n throw new InputError(`entity query must be a string`);\n } else if (!rawEntityRef) {\n throw new InputError('entity is a required field');\n }\n let entityRef: CompoundEntityRef | undefined = undefined;\n\n try {\n entityRef = parseEntityRef(rawEntityRef);\n } catch (error) {\n throw new InputError(`Invalid entity ref, ${error}`);\n }\n\n const token = getBearerTokenFromAuthorizationHeader(\n req.headers.authorization,\n );\n\n if (!token) {\n throw new AuthenticationError('No Backstage token');\n }\n\n const entity = await catalogApi.getEntityByRef(entityRef, {\n token: token,\n });\n\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity,\n auth: req.body.auth,\n });\n res.json(response);\n });\n\n router.post('/resources/custom/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n\n if (!req.body.customResources) {\n throw new InputError('customResources is a required field');\n } else if (!Array.isArray(req.body.customResources)) {\n throw new InputError('customResources must be an array');\n } else if (req.body.customResources.length === 0) {\n throw new InputError('at least 1 customResource is required');\n }\n\n const response = await objectsProvider.getCustomResourcesByEntity({\n entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n });\n res.json(response);\n });\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n ServiceLocatorRequestContext,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n getClustersByEntity(\n _entity: Entity,\n _requestContext: ServiceLocatorRequestContext,\n ): Promise<{ clusters: ClusterDetails[] }> {\n return this.clusterSupplier.getClusters().then(clusters => ({ clusters }));\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n CustomResource,\n CustomResourcesByEntity,\n KubernetesObjectsByEntity,\n ServiceLocatorRequestContext,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n KubernetesRequestAuth,\n CustomResourceMatcher,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\n/**\n *\n * @alpha\n */\nexport const DEFAULT_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'pods',\n objectType: 'pods',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'services',\n objectType: 'services',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'configmaps',\n objectType: 'configmaps',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'limitranges',\n objectType: 'limitranges',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'daemonsets',\n objectType: 'daemonsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: PodStatusFetchResponse[],\n): ClientPodStatus[] => {\n return podMetrics\n .map(r => r.resources)\n .flat()\n .map((pd: PodStatus): ClientPodStatus => {\n return {\n pod: pd.Pod,\n memory: toClientSafeResource(pd.Memory),\n cpu: toClientSafeResource(pd.CPU),\n containers: pd.Containers.map(toClientSafeContainer),\n };\n });\n};\n\ntype responseWithMetrics = [FetchResponseWrapper, PodStatusFetchResponse[]];\n\nexport class KubernetesFanOutHandler {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslators: Record<string, KubernetesAuthTranslator>;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n }: KubernetesFanOutHandlerOptions) {\n this.logger = logger;\n this.fetcher = fetcher;\n this.serviceLocator = serviceLocator;\n this.customResources = customResources;\n this.objectTypesToFetch = new Set(objectTypesToFetch);\n this.authTranslators = {};\n }\n\n async getCustomResourcesByEntity({\n entity,\n auth,\n customResources,\n }: CustomResourcesByEntity): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity({\n entity,\n auth,\n }: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(entity, auth, this.objectTypesToFetch);\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n objectTypesToFetch: Set<ObjectToFetch>,\n customResources?: CustomResourceMatcher[],\n ) {\n const entityName =\n entity.metadata?.annotations?.['backstage.io/kubernetes-id'] ||\n entity.metadata?.name;\n\n const clusterDetailsDecoratedForAuth: ClusterDetails[] =\n await this.decorateClusterDetailsWithAuth(entity, auth, {\n objectTypesToFetch: objectTypesToFetch,\n customResources: customResources ?? [],\n });\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: objectTypesToFetch,\n labelSelector,\n customResources: (\n customResources ||\n clusterDetailsItem.customResources ||\n this.customResources\n ).map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\n .catch(\n (e): Promise<responseWithMetrics> =>\n e.name === 'FetchError'\n ? Promise.resolve([\n {\n errors: [\n { errorType: 'FETCH_ERROR', message: e.message },\n ],\n responses: [],\n },\n [],\n ])\n : Promise.reject(e),\n )\n .then(r => this.toClusterObjects(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n private async decorateClusterDetailsWithAuth(\n entity: Entity,\n auth: KubernetesRequestAuth,\n requestContext: ServiceLocatorRequestContext,\n ) {\n const clusterDetails: ClusterDetails[] = await (\n await this.serviceLocator.getClustersByEntity(entity, requestContext)\n ).clusters;\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n return await Promise.all(\n clusterDetails.map(cd => {\n const kubernetesAuthTranslator: KubernetesAuthTranslator =\n this.getAuthTranslator(cd.authProvider);\n return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(\n cd,\n auth,\n );\n }),\n );\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n if (namespaces.size === 0) {\n return [result, []];\n }\n\n const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces(\n clusterDetails,\n namespaces,\n );\n\n result.errors.push(...podMetrics.errors);\n return [result, podMetrics.responses as PodStatusFetchResponse[]];\n }\n\n private getAuthTranslator(provider: string): KubernetesAuthTranslator {\n if (this.authTranslators[provider]) {\n return this.authTranslators[provider];\n }\n\n this.authTranslators[provider] =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n provider,\n {\n logger: this.logger,\n },\n );\n return this.authTranslators[provider];\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Config,\n Cluster,\n CoreV1Api,\n KubeConfig,\n Metrics,\n User,\n bufferFromFileOrString,\n topPods,\n} from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n ObjectFetchParams,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport fetch, { RequestInit, Response } from 'node-fetch';\nimport * as https from 'https';\nimport fs from 'fs-extra';\n\nexport interface KubernetesClientBasedFetcherOptions {\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 404:\n return 'NOT_FOUND';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly logger: Logger;\n\n constructor({ logger }: KubernetesClientBasedFetcherOptions) {\n this.logger = logger;\n }\n\n fetchObjectsForService(\n params: ObjectFetchParams,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(params.objectTypesToFetch)\n .concat(params.customResources)\n .map(({ objectType, group, apiVersion, plural }) =>\n this.fetchResource(\n params.clusterDetails,\n group,\n apiVersion,\n plural,\n params.namespace,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n ).then(\n (r: Response): Promise<FetchResult> =>\n r.ok\n ? r.json().then(\n ({ items }): FetchResponse => ({\n type: objectType,\n resources: items,\n }),\n )\n : this.handleUnsuccessfulResponse(params.clusterDetails.name, r),\n ),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespaces(\n clusterDetails: ClusterDetails,\n namespaces: Set<string>,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(namespaces).map(async ns => {\n const [podMetrics, podList] = await Promise.all([\n this.fetchResource(\n clusterDetails,\n 'metrics.k8s.io',\n 'v1beta1',\n 'pods',\n ns,\n ),\n this.fetchResource(clusterDetails, '', 'v1', 'pods', ns),\n ]);\n if (podMetrics.ok && podList.ok) {\n return topPods(\n {\n listPodForAllNamespaces: () =>\n podList.json().then(b => ({ body: b })),\n } as unknown as CoreV1Api,\n {\n getPodMetrics: () => podMetrics.json(),\n } as unknown as Metrics,\n ).then(\n (resources): PodStatusFetchResponse => ({\n type: 'podstatus',\n resources,\n }),\n );\n } else if (podMetrics.ok) {\n return this.handleUnsuccessfulResponse(clusterDetails.name, podList);\n }\n return this.handleUnsuccessfulResponse(clusterDetails.name, podMetrics);\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n private async handleUnsuccessfulResponse(\n clusterName: string,\n res: Response,\n ): Promise<KubernetesFetchError> {\n const resourcePath = new URL(res.url).pathname;\n this.logger.warn(\n `Received ${\n res.status\n } status when fetching \"${resourcePath}\" from cluster \"${clusterName}\"; body=[${await res.text()}]`,\n );\n return {\n errorType: statusCodeToErrorType(res.status),\n statusCode: res.status,\n resourcePath,\n };\n }\n\n private fetchResource(\n clusterDetails: ClusterDetails,\n group: string,\n apiVersion: string,\n plural: string,\n namespace?: string,\n labelSelector?: string,\n ): Promise<Response> {\n const encode = (s: string) => encodeURIComponent(s);\n let resourcePath = group\n ? `/apis/${encode(group)}/${encode(apiVersion)}`\n : `/api/${encode(apiVersion)}`;\n if (namespace) {\n resourcePath += `/namespaces/${encode(namespace)}`;\n }\n resourcePath += `/${encode(plural)}`;\n\n let url: URL;\n let requestInit: RequestInit;\n if (clusterDetails.serviceAccountToken) {\n [url, requestInit] = this.fetchArgsFromClusterDetails(clusterDetails);\n } else if (fs.pathExistsSync(Config.SERVICEACCOUNT_TOKEN_PATH)) {\n [url, requestInit] = this.fetchArgsInCluster();\n } else {\n return Promise.reject(\n new Error(\n `no bearer token for cluster '${clusterDetails.name}' and not running in Kubernetes`,\n ),\n );\n }\n\n if (url.pathname === '/') {\n url.pathname = resourcePath;\n } else {\n url.pathname += resourcePath;\n }\n\n if (labelSelector) {\n url.search = `labelSelector=${labelSelector}`;\n }\n\n return fetch(url, requestInit);\n }\n\n private fetchArgsFromClusterDetails(\n clusterDetails: ClusterDetails,\n ): [URL, RequestInit] {\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${clusterDetails.serviceAccountToken}`,\n },\n };\n\n const url: URL = new URL(clusterDetails.url);\n if (url.protocol === 'https:') {\n requestInit.agent = new https.Agent({\n ca:\n bufferFromFileOrString(\n clusterDetails.caFile,\n clusterDetails.caData,\n ) ?? undefined,\n rejectUnauthorized: !clusterDetails.skipTLSVerify,\n });\n }\n return [url, requestInit];\n }\n private fetchArgsInCluster(): [URL, RequestInit] {\n const kc = new KubeConfig();\n kc.loadFromCluster();\n // loadFromCluster is guaranteed to populate the cluster/user/context\n const cluster = kc.getCurrentCluster() as Cluster;\n const user = kc.getCurrentUser() as User;\n\n const token = fs.readFileSync(user.authProvider.config.tokenFile);\n\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n };\n\n const url = new URL(cluster.server);\n if (url.protocol === 'https:') {\n requestInit.agent = new https.Agent({\n ca: fs.readFileSync(cluster.caFile as string),\n });\n }\n return [url, requestInit];\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ErrorResponseBody,\n ForwardedError,\n InputError,\n NotFoundError,\n serializeError,\n} from '@backstage/errors';\nimport { bufferFromFileOrString } from '@kubernetes/client-node';\nimport type { Request, RequestHandler } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\nimport { Logger } from 'winston';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport const APPLICATION_JSON: string = 'application/json';\n\n/**\n * The header that is used to specify the cluster name.\n *\n * @alpha\n */\nexport const HEADER_KUBERNETES_CLUSTER: string = 'X-Kubernetes-Cluster';\n\n/**\n * A proxy that routes requests to the Kubernetes API.\n *\n * @alpha\n */\nexport class KubernetesProxy {\n private readonly middlewareForClusterName = new Map<string, RequestHandler>();\n\n constructor(\n private readonly logger: Logger,\n private readonly clusterSupplier: KubernetesClustersSupplier,\n ) {}\n\n public createRequestHandler(): RequestHandler {\n return async (req, res, next) => {\n const middleware = await this.getMiddleware(req);\n middleware(req, res, next);\n };\n }\n\n // We create one middleware per remote cluster and hold on to them, because\n // the secure property isn't possible to decide on a per-request basis with a\n // single middleware instance - and we don't expect it to change over time.\n private async getMiddleware(originalReq: Request): Promise<RequestHandler> {\n const originalCluster = await this.getClusterForRequest(originalReq);\n let middleware = this.middlewareForClusterName.get(originalCluster.name);\n if (!middleware) {\n // Probably too risky without permissions protecting this endpoint\n // if (cluster.serviceAccountToken) {\n // options.headers = {\n // Authorization: `Bearer ${cluster.serviceAccountToken}`,\n // };\n // }\n\n const logger = this.logger.child({ cluster: originalCluster.name });\n middleware = createProxyMiddleware({\n logProvider: () => logger,\n secure: !originalCluster.skipTLSVerify,\n router: async req => {\n // Re-evaluate the cluster on each request, in case it has changed\n const cluster = await this.getClusterForRequest(req);\n const url = new URL(cluster.url);\n return {\n protocol: url.protocol,\n host: url.hostname,\n port: url.port,\n ca: bufferFromFileOrString('', cluster.caData)?.toString(),\n };\n },\n pathRewrite: { [`^${originalReq.baseUrl}`]: '' },\n onError: (error, req, res) => {\n const wrappedError = new ForwardedError(\n `Cluster '${originalCluster.name}' request error`,\n error,\n );\n\n logger.error(wrappedError);\n\n const body: ErrorResponseBody = {\n error: serializeError(wrappedError, {\n includeStack: process.env.NODE_ENV === 'development',\n }),\n request: { method: req.method, url: req.originalUrl },\n response: { statusCode: 500 },\n };\n\n res.status(500).json(body);\n },\n });\n\n this.middlewareForClusterName.set(originalCluster.name, middleware);\n }\n\n return middleware;\n }\n\n private async getClusterForRequest(req: Request): Promise<ClusterDetails> {\n const clusterName = req.header(HEADER_KUBERNETES_CLUSTER);\n if (!clusterName) {\n throw new InputError(`Missing '${HEADER_KUBERNETES_CLUSTER}' header.`);\n }\n\n const cluster = await this.clusterSupplier\n .getClusters()\n .then(clusters => clusters.find(c => c.name === clusterName));\n if (!cluster) {\n throw new NotFoundError(`Cluster '${clusterName}' not found`);\n }\n\n return cluster;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Duration } from 'luxon';\nimport { Logger } from 'winston';\n\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { addResourceRoutesToRouter } from '../routes/resourcesRoutes';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n CustomResource,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesObjectsProvider,\n KubernetesObjectsProviderOptions,\n KubernetesObjectTypes,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n ServiceLocatorMethod,\n} from '../types/types';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\nimport { KubernetesProxy } from './KubernetesProxy';\n\n/**\n *\n * @alpha\n */\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @alpha\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n proxy: KubernetesProxy;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\n/**\n *\n * @alpha\n */\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n private proxy?: KubernetesProxy;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.getFetcher();\n\n const clusterSupplier = this.getClusterSupplier();\n\n const proxy = this.getProxy(logger, clusterSupplier);\n\n const serviceLocator = this.getServiceLocator();\n\n const objectsProvider = this.getObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(\n objectsProvider,\n clusterSupplier,\n this.env.catalogApi,\n proxy,\n );\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n proxy,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n public setProxy(proxy?: KubernetesProxy) {\n this.proxy = proxy;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n this.clusterSupplier = getCombinedClusterSupplier(\n config,\n this.env.catalogApi,\n refreshInterval,\n );\n\n return this.clusterSupplier;\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n this.objectsProvider = new KubernetesFanOutHandler(options);\n return this.objectsProvider;\n }\n\n protected buildFetcher(): KubernetesFetcher {\n this.fetcher = new KubernetesClientBasedFetcher({\n logger: this.env.logger,\n });\n\n return this.fetcher;\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n this.serviceLocator =\n this.buildMultiTenantServiceLocator(clusterSupplier);\n break;\n case 'http':\n this.serviceLocator = this.buildHttpServiceLocator(clusterSupplier);\n break;\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n\n return this.serviceLocator;\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesProxy {\n this.proxy = new KubernetesProxy(logger, clusterSupplier);\n return this.proxy;\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n catalogApi: CatalogApi,\n proxy: KubernetesProxy,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use('/proxy', proxy.createRequestHandler());\n router.use(express.json());\n\n // @deprecated\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity: requestBody.entity,\n auth: requestBody.auth || {},\n });\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n\n addResourceRoutesToRouter(router, catalogApi, objectsProvider);\n\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getFetcher(): KubernetesFetcher {\n return this.fetcher ?? this.buildFetcher();\n }\n\n protected getClusterSupplier() {\n return (\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval)\n );\n }\n\n protected getServiceLocator(): KubernetesServiceLocator {\n return (\n this.serviceLocator ??\n this.buildServiceLocator(\n this.getServiceLocatorMethod(),\n this.getClusterSupplier(),\n )\n );\n }\n\n protected getObjectsProvider(options: KubernetesObjectsProviderOptions) {\n return this.objectsProvider ?? this.buildObjectsProvider(options);\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\n }\n\n protected getProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n return this.proxy ?? this.buildProxy(logger, clusterSupplier);\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\nimport { PluginEndpointDiscovery } from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\n\n/**\n *\n * @alpha\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n clusterSupplier?: KubernetesClustersSupplier;\n discovery: PluginEndpointDiscovery;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n *\n * @alpha\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["AWS","Credentials","sign","DefaultAzureCredential","container","_a","ForwardedError","ANNOTATION_KUBERNETES_API_SERVER","ANNOTATION_KUBERNETES_API_SERVER_CA","ANNOTATION_KUBERNETES_AUTH_PROVIDER","CATALOG_FILTER_EXISTS","ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER","ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP","ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY","ANNOTATION_KUBERNETES_DASHBOARD_URL","ANNOTATION_KUBERNETES_DASHBOARD_APP","InputError","parseEntityRef","getBearerTokenFromAuthorizationHeader","AuthenticationError","stringifyEntityRef","lodash","topPods","fs","Config","fetch","https","bufferFromFileOrString","KubeConfig","createProxyMiddleware","serializeError","NotFoundError","Duration","Router","express"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/CatalogClusterLocator.ts","../src/cluster-locator/LocalKubectlProxyLocator.ts","../src/cluster-locator/index.ts","../src/routes/resourcesRoutes.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesProxy.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\n/**\n *\n * @public\n */\nexport type SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\n/**\n *\n * @public\n */\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n 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 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\n/**\n *\n * @public\n */\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = authConfig.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\n/**\n *\n * @public\n */\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\n\n/**\n *\n * @public\n */\nexport class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @public\n */\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined = authConfig.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { NoopKubernetesAuthTranslator } from './NoopKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\n/**\n *\n * @public\n */\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n options: {\n logger: Logger;\n },\n ): KubernetesAuthTranslator {\n switch (authProvider) {\n case 'google': {\n return new GoogleKubernetesAuthTranslator();\n }\n case 'aws': {\n return new AwsIamKubernetesAuthTranslator();\n }\n case 'azure': {\n return new AzureIdentityKubernetesAuthTranslator(options.logger);\n }\n case 'serviceAccount': {\n return new NoopKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n case 'localKubectlProxy': {\n return new NoopKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\n }\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n caFile: c.getOptionalString('caFile'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\n );\n }\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { CATALOG_FILTER_EXISTS, CatalogApi } from '@backstage/catalog-client';\nimport {\n ANNOTATION_KUBERNETES_API_SERVER,\n ANNOTATION_KUBERNETES_API_SERVER_CA,\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER,\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP,\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY,\n ANNOTATION_KUBERNETES_DASHBOARD_URL,\n ANNOTATION_KUBERNETES_DASHBOARD_APP,\n} from '@backstage/plugin-kubernetes-common';\n\nexport class CatalogClusterLocator implements KubernetesClustersSupplier {\n private catalogClient: CatalogApi;\n\n constructor(catalogClient: CatalogApi) {\n this.catalogClient = catalogClient;\n }\n\n static fromConfig(catalogApi: CatalogApi): CatalogClusterLocator {\n return new CatalogClusterLocator(catalogApi);\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n const apiServerKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER}`;\n const apiServerCaKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER_CA}`;\n const authProviderKey = `metadata.annotations.${ANNOTATION_KUBERNETES_AUTH_PROVIDER}`;\n\n const filter: Record<string, symbol | string> = {\n kind: 'Resource',\n 'spec.type': 'kubernetes-cluster',\n [apiServerKey]: CATALOG_FILTER_EXISTS,\n [apiServerCaKey]: CATALOG_FILTER_EXISTS,\n [authProviderKey]: CATALOG_FILTER_EXISTS,\n };\n\n const clusters = await this.catalogClient.getEntities({\n filter: [filter],\n });\n return clusters.items.map(entity => {\n const clusterDetails: ClusterDetails = {\n name: entity.metadata.name,\n url: entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER]!,\n caData:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER_CA]!,\n authProvider:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_AUTH_PROVIDER]!,\n oidcTokenProvider:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER\n ]!,\n skipMetricsLookup:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP\n ]! === 'true'\n ? true\n : false,\n skipTLSVerify:\n entity.metadata.annotations![\n ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY\n ]! === 'true'\n ? true\n : false,\n dashboardUrl:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_URL]!,\n dashboardApp:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_DASHBOARD_APP]!,\n };\n\n return clusterDetails;\n });\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class LocalKubectlProxyClusterLocator\n implements KubernetesClustersSupplier\n{\n private readonly clusterDetails: ClusterDetails[];\n\n public constructor() {\n this.clusterDetails = [\n {\n name: 'local',\n url: 'http:/localhost:8001',\n authProvider: 'localKubectlProxy',\n skipMetricsLookup: true,\n },\n ];\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\nimport { CatalogClusterLocator } from './CatalogClusterLocator';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { LocalKubectlProxyClusterLocator } from './LocalKubectlProxyLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n catalogClient: CatalogApi,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'catalog':\n return CatalogClusterLocator.fromConfig(catalogClient);\n case 'localKubectlProxy':\n return new LocalKubectlProxyClusterLocator();\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\n};\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n CompoundEntityRef,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { InputError, AuthenticationError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '../types/types';\nimport { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalogApi: CatalogApi,\n objectsProvider: KubernetesObjectsProvider,\n) => {\n const getEntityByReq = async (req: Request<any>) => {\n const rawEntityRef = req.body.entityRef;\n if (rawEntityRef && typeof rawEntityRef !== 'string') {\n throw new InputError(`entity query must be a string`);\n } else if (!rawEntityRef) {\n throw new InputError('entity is a required field');\n }\n let entityRef: CompoundEntityRef | undefined = undefined;\n\n try {\n entityRef = parseEntityRef(rawEntityRef);\n } catch (error) {\n throw new InputError(`Invalid entity ref, ${error}`);\n }\n\n const token = getBearerTokenFromAuthorizationHeader(\n req.headers.authorization,\n );\n\n if (!token) {\n throw new AuthenticationError('No Backstage token');\n }\n\n const entity = await catalogApi.getEntityByRef(entityRef, {\n token: token,\n });\n\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity,\n auth: req.body.auth,\n });\n res.json(response);\n });\n\n router.post('/resources/custom/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n\n if (!req.body.customResources) {\n throw new InputError('customResources is a required field');\n } else if (!Array.isArray(req.body.customResources)) {\n throw new InputError('customResources must be an array');\n } else if (req.body.customResources.length === 0) {\n throw new InputError('at least 1 customResource is required');\n }\n\n const response = await objectsProvider.getCustomResourcesByEntity({\n entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n });\n res.json(response);\n });\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n ServiceLocatorRequestContext,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n getClustersByEntity(\n _entity: Entity,\n _requestContext: ServiceLocatorRequestContext,\n ): Promise<{ clusters: ClusterDetails[] }> {\n return this.clusterSupplier.getClusters().then(clusters => ({ clusters }));\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n CustomResource,\n CustomResourcesByEntity,\n KubernetesObjectsByEntity,\n ServiceLocatorRequestContext,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n KubernetesRequestAuth,\n CustomResourceMatcher,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\n/**\n *\n * @public\n */\nexport const DEFAULT_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'pods',\n objectType: 'pods',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'services',\n objectType: 'services',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'configmaps',\n objectType: 'configmaps',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'limitranges',\n objectType: 'limitranges',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'daemonsets',\n objectType: 'daemonsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: PodStatusFetchResponse[],\n): ClientPodStatus[] => {\n return podMetrics\n .map(r => r.resources)\n .flat()\n .map((pd: PodStatus): ClientPodStatus => {\n return {\n pod: pd.Pod,\n memory: toClientSafeResource(pd.Memory),\n cpu: toClientSafeResource(pd.CPU),\n containers: pd.Containers.map(toClientSafeContainer),\n };\n });\n};\n\ntype responseWithMetrics = [FetchResponseWrapper, PodStatusFetchResponse[]];\n\nexport class KubernetesFanOutHandler {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslators: Record<string, KubernetesAuthTranslator>;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n }: KubernetesFanOutHandlerOptions) {\n this.logger = logger;\n this.fetcher = fetcher;\n this.serviceLocator = serviceLocator;\n this.customResources = customResources;\n this.objectTypesToFetch = new Set(objectTypesToFetch);\n this.authTranslators = {};\n }\n\n async getCustomResourcesByEntity({\n entity,\n auth,\n customResources,\n }: CustomResourcesByEntity): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity({\n entity,\n auth,\n }: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(entity, auth, this.objectTypesToFetch);\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n objectTypesToFetch: Set<ObjectToFetch>,\n customResources?: CustomResourceMatcher[],\n ) {\n const entityName =\n entity.metadata?.annotations?.['backstage.io/kubernetes-id'] ||\n entity.metadata?.name;\n\n const clusterDetailsDecoratedForAuth: ClusterDetails[] =\n await this.decorateClusterDetailsWithAuth(entity, auth, {\n objectTypesToFetch: objectTypesToFetch,\n customResources: customResources ?? [],\n });\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: objectTypesToFetch,\n labelSelector,\n customResources: (\n customResources ||\n clusterDetailsItem.customResources ||\n this.customResources\n ).map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\n .catch(\n (e): Promise<responseWithMetrics> =>\n e.name === 'FetchError'\n ? Promise.resolve([\n {\n errors: [\n { errorType: 'FETCH_ERROR', message: e.message },\n ],\n responses: [],\n },\n [],\n ])\n : Promise.reject(e),\n )\n .then(r => this.toClusterObjects(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n private async decorateClusterDetailsWithAuth(\n entity: Entity,\n auth: KubernetesRequestAuth,\n requestContext: ServiceLocatorRequestContext,\n ) {\n const clusterDetails: ClusterDetails[] = await (\n await this.serviceLocator.getClustersByEntity(entity, requestContext)\n ).clusters;\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n return await Promise.all(\n clusterDetails.map(cd => {\n const kubernetesAuthTranslator: KubernetesAuthTranslator =\n this.getAuthTranslator(cd.authProvider);\n return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(\n cd,\n auth,\n );\n }),\n );\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n if (namespaces.size === 0) {\n return [result, []];\n }\n\n const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces(\n clusterDetails,\n namespaces,\n );\n\n result.errors.push(...podMetrics.errors);\n return [result, podMetrics.responses as PodStatusFetchResponse[]];\n }\n\n private getAuthTranslator(provider: string): KubernetesAuthTranslator {\n if (this.authTranslators[provider]) {\n return this.authTranslators[provider];\n }\n\n this.authTranslators[provider] =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n provider,\n {\n logger: this.logger,\n },\n );\n return this.authTranslators[provider];\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Config,\n Cluster,\n CoreV1Api,\n KubeConfig,\n Metrics,\n User,\n bufferFromFileOrString,\n topPods,\n} from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n ObjectFetchParams,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport fetch, { RequestInit, Response } from 'node-fetch';\nimport * as https from 'https';\nimport fs from 'fs-extra';\n\nexport interface KubernetesClientBasedFetcherOptions {\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 404:\n return 'NOT_FOUND';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly logger: Logger;\n\n constructor({ logger }: KubernetesClientBasedFetcherOptions) {\n this.logger = logger;\n }\n\n fetchObjectsForService(\n params: ObjectFetchParams,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(params.objectTypesToFetch)\n .concat(params.customResources)\n .map(({ objectType, group, apiVersion, plural }) =>\n this.fetchResource(\n params.clusterDetails,\n group,\n apiVersion,\n plural,\n params.namespace,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n ).then(\n (r: Response): Promise<FetchResult> =>\n r.ok\n ? r.json().then(\n ({ items }): FetchResponse => ({\n type: objectType,\n resources: items,\n }),\n )\n : this.handleUnsuccessfulResponse(params.clusterDetails.name, r),\n ),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespaces(\n clusterDetails: ClusterDetails,\n namespaces: Set<string>,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(namespaces).map(async ns => {\n const [podMetrics, podList] = await Promise.all([\n this.fetchResource(\n clusterDetails,\n 'metrics.k8s.io',\n 'v1beta1',\n 'pods',\n ns,\n ),\n this.fetchResource(clusterDetails, '', 'v1', 'pods', ns),\n ]);\n if (podMetrics.ok && podList.ok) {\n return topPods(\n {\n listPodForAllNamespaces: () =>\n podList.json().then(b => ({ body: b })),\n } as unknown as CoreV1Api,\n {\n getPodMetrics: () => podMetrics.json(),\n } as unknown as Metrics,\n ).then(\n (resources): PodStatusFetchResponse => ({\n type: 'podstatus',\n resources,\n }),\n );\n } else if (podMetrics.ok) {\n return this.handleUnsuccessfulResponse(clusterDetails.name, podList);\n }\n return this.handleUnsuccessfulResponse(clusterDetails.name, podMetrics);\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n private async handleUnsuccessfulResponse(\n clusterName: string,\n res: Response,\n ): Promise<KubernetesFetchError> {\n const resourcePath = new URL(res.url).pathname;\n this.logger.warn(\n `Received ${\n res.status\n } status when fetching \"${resourcePath}\" from cluster \"${clusterName}\"; body=[${await res.text()}]`,\n );\n return {\n errorType: statusCodeToErrorType(res.status),\n statusCode: res.status,\n resourcePath,\n };\n }\n\n private fetchResource(\n clusterDetails: ClusterDetails,\n group: string,\n apiVersion: string,\n plural: string,\n namespace?: string,\n labelSelector?: string,\n ): Promise<Response> {\n const encode = (s: string) => encodeURIComponent(s);\n let resourcePath = group\n ? `/apis/${encode(group)}/${encode(apiVersion)}`\n : `/api/${encode(apiVersion)}`;\n if (namespace) {\n resourcePath += `/namespaces/${encode(namespace)}`;\n }\n resourcePath += `/${encode(plural)}`;\n\n let url: URL;\n let requestInit: RequestInit;\n if (clusterDetails.serviceAccountToken) {\n [url, requestInit] = this.fetchArgsFromClusterDetails(clusterDetails);\n } else if (fs.pathExistsSync(Config.SERVICEACCOUNT_TOKEN_PATH)) {\n [url, requestInit] = this.fetchArgsInCluster();\n } else {\n return Promise.reject(\n new Error(\n `no bearer token for cluster '${clusterDetails.name}' and not running in Kubernetes`,\n ),\n );\n }\n\n if (url.pathname === '/') {\n url.pathname = resourcePath;\n } else {\n url.pathname += resourcePath;\n }\n\n if (labelSelector) {\n url.search = `labelSelector=${labelSelector}`;\n }\n\n return fetch(url, requestInit);\n }\n\n private fetchArgsFromClusterDetails(\n clusterDetails: ClusterDetails,\n ): [URL, RequestInit] {\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${clusterDetails.serviceAccountToken}`,\n },\n };\n\n const url: URL = new URL(clusterDetails.url);\n if (url.protocol === 'https:') {\n requestInit.agent = new https.Agent({\n ca:\n bufferFromFileOrString(\n clusterDetails.caFile,\n clusterDetails.caData,\n ) ?? undefined,\n rejectUnauthorized: !clusterDetails.skipTLSVerify,\n });\n }\n return [url, requestInit];\n }\n private fetchArgsInCluster(): [URL, RequestInit] {\n const kc = new KubeConfig();\n kc.loadFromCluster();\n // loadFromCluster is guaranteed to populate the cluster/user/context\n const cluster = kc.getCurrentCluster() as Cluster;\n const user = kc.getCurrentUser() as User;\n\n const token = fs.readFileSync(user.authProvider.config.tokenFile);\n\n const requestInit: RequestInit = {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n };\n\n const url = new URL(cluster.server);\n if (url.protocol === 'https:') {\n requestInit.agent = new https.Agent({\n ca: fs.readFileSync(cluster.caFile as string),\n });\n }\n return [url, requestInit];\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ErrorResponseBody,\n ForwardedError,\n InputError,\n NotFoundError,\n serializeError,\n} from '@backstage/errors';\nimport { bufferFromFileOrString } from '@kubernetes/client-node';\nimport type { Request, RequestHandler } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\nimport { Logger } from 'winston';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport const APPLICATION_JSON: string = 'application/json';\n\n/**\n * The header that is used to specify the cluster name.\n *\n * @public\n */\nexport const HEADER_KUBERNETES_CLUSTER: string = 'X-Kubernetes-Cluster';\n\n/**\n * A proxy that routes requests to the Kubernetes API.\n *\n * @public\n */\nexport class KubernetesProxy {\n private readonly middlewareForClusterName = new Map<string, RequestHandler>();\n\n constructor(\n private readonly logger: Logger,\n private readonly clusterSupplier: KubernetesClustersSupplier,\n ) {}\n\n public createRequestHandler(): RequestHandler {\n return async (req, res, next) => {\n const middleware = await this.getMiddleware(req);\n middleware(req, res, next);\n };\n }\n\n // We create one middleware per remote cluster and hold on to them, because\n // the secure property isn't possible to decide on a per-request basis with a\n // single middleware instance - and we don't expect it to change over time.\n private async getMiddleware(originalReq: Request): Promise<RequestHandler> {\n const originalCluster = await this.getClusterForRequest(originalReq);\n let middleware = this.middlewareForClusterName.get(originalCluster.name);\n if (!middleware) {\n // Probably too risky without permissions protecting this endpoint\n // if (cluster.serviceAccountToken) {\n // options.headers = {\n // Authorization: `Bearer ${cluster.serviceAccountToken}`,\n // };\n // }\n\n const logger = this.logger.child({ cluster: originalCluster.name });\n middleware = createProxyMiddleware({\n logProvider: () => logger,\n secure: !originalCluster.skipTLSVerify,\n router: async req => {\n // Re-evaluate the cluster on each request, in case it has changed\n const cluster = await this.getClusterForRequest(req);\n const url = new URL(cluster.url);\n return {\n protocol: url.protocol,\n host: url.hostname,\n port: url.port,\n ca: bufferFromFileOrString('', cluster.caData)?.toString(),\n };\n },\n pathRewrite: { [`^${originalReq.baseUrl}`]: '' },\n onError: (error, req, res) => {\n const wrappedError = new ForwardedError(\n `Cluster '${originalCluster.name}' request error`,\n error,\n );\n\n logger.error(wrappedError);\n\n const body: ErrorResponseBody = {\n error: serializeError(wrappedError, {\n includeStack: process.env.NODE_ENV === 'development',\n }),\n request: { method: req.method, url: req.originalUrl },\n response: { statusCode: 500 },\n };\n\n res.status(500).json(body);\n },\n });\n\n this.middlewareForClusterName.set(originalCluster.name, middleware);\n }\n\n return middleware;\n }\n\n private async getClusterForRequest(req: Request): Promise<ClusterDetails> {\n const clusterName = req.header(HEADER_KUBERNETES_CLUSTER);\n if (!clusterName) {\n throw new InputError(`Missing '${HEADER_KUBERNETES_CLUSTER}' header.`);\n }\n\n const cluster = await this.clusterSupplier\n .getClusters()\n .then(clusters => clusters.find(c => c.name === clusterName));\n if (!cluster) {\n throw new NotFoundError(`Cluster '${clusterName}' not found`);\n }\n\n return cluster;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Duration } from 'luxon';\nimport { Logger } from 'winston';\n\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { addResourceRoutesToRouter } from '../routes/resourcesRoutes';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n CustomResource,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesObjectsProvider,\n KubernetesObjectsProviderOptions,\n KubernetesObjectTypes,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n ServiceLocatorMethod,\n} from '../types/types';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\nimport { KubernetesProxy } from './KubernetesProxy';\n\n/**\n *\n * @public\n */\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @public\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n proxy: KubernetesProxy;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\n/**\n *\n * @public\n */\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n private proxy?: KubernetesProxy;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.getFetcher();\n\n const clusterSupplier = this.getClusterSupplier();\n\n const proxy = this.getProxy(logger, clusterSupplier);\n\n const serviceLocator = this.getServiceLocator();\n\n const objectsProvider = this.getObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(\n objectsProvider,\n clusterSupplier,\n this.env.catalogApi,\n proxy,\n );\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n proxy,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n public setProxy(proxy?: KubernetesProxy) {\n this.proxy = proxy;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n this.clusterSupplier = getCombinedClusterSupplier(\n config,\n this.env.catalogApi,\n refreshInterval,\n );\n\n return this.clusterSupplier;\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n this.objectsProvider = new KubernetesFanOutHandler(options);\n return this.objectsProvider;\n }\n\n protected buildFetcher(): KubernetesFetcher {\n this.fetcher = new KubernetesClientBasedFetcher({\n logger: this.env.logger,\n });\n\n return this.fetcher;\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n this.serviceLocator =\n this.buildMultiTenantServiceLocator(clusterSupplier);\n break;\n case 'http':\n this.serviceLocator = this.buildHttpServiceLocator(clusterSupplier);\n break;\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n\n return this.serviceLocator;\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesProxy {\n this.proxy = new KubernetesProxy(logger, clusterSupplier);\n return this.proxy;\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n catalogApi: CatalogApi,\n proxy: KubernetesProxy,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use('/proxy', proxy.createRequestHandler());\n router.use(express.json());\n\n // @deprecated\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity: requestBody.entity,\n auth: requestBody.auth || {},\n });\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n\n addResourceRoutesToRouter(router, catalogApi, objectsProvider);\n\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getFetcher(): KubernetesFetcher {\n return this.fetcher ?? this.buildFetcher();\n }\n\n protected getClusterSupplier() {\n return (\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval)\n );\n }\n\n protected getServiceLocator(): KubernetesServiceLocator {\n return (\n this.serviceLocator ??\n this.buildServiceLocator(\n this.getServiceLocatorMethod(),\n this.getClusterSupplier(),\n )\n );\n }\n\n protected getObjectsProvider(options: KubernetesObjectsProviderOptions) {\n return this.objectsProvider ?? this.buildObjectsProvider(options);\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\n }\n\n protected getProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n return this.proxy ?? this.buildProxy(logger, clusterSupplier);\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\nimport { PluginEndpointDiscovery } from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\n\n/**\n *\n * @public\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n clusterSupplier?: KubernetesClustersSupplier;\n discovery: PluginEndpointDiscovery;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["AWS","Credentials","sign","DefaultAzureCredential","container","_a","ForwardedError","ANNOTATION_KUBERNETES_API_SERVER","ANNOTATION_KUBERNETES_API_SERVER_CA","ANNOTATION_KUBERNETES_AUTH_PROVIDER","CATALOG_FILTER_EXISTS","ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER","ANNOTATION_KUBERNETES_SKIP_METRICS_LOOKUP","ANNOTATION_KUBERNETES_SKIP_TLS_VERIFY","ANNOTATION_KUBERNETES_DASHBOARD_URL","ANNOTATION_KUBERNETES_DASHBOARD_APP","InputError","parseEntityRef","getBearerTokenFromAuthorizationHeader","AuthenticationError","stringifyEntityRef","lodash","topPods","fs","Config","fetch","https","bufferFromFileOrString","KubeConfig","createProxyMiddleware","serializeError","NotFoundError","Duration","Router","express"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCO,MAAM,8BAEb,CAAA;AAAA,EAFO,WAAA,GAAA;AAOL,IAAA,IAAA,CAAA,iBAAA,GAAoB,YAAkC;AACpD,MAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAW,KAAA;AACtC,QAAIA,uBAAA,CAAA,MAAA,CAAO,eAAe,CAAO,GAAA,KAAA;AAC/B,UAAA,IAAI,GAAK,EAAA;AACP,YAAA,OAAO,OAAO,GAAG,CAAA,CAAA;AAAA,WACnB;AAEA,UAAO,OAAA,OAAA,CAAQA,uBAAI,CAAA,MAAA,CAAO,WAA0B,CAAA,CAAA;AAAA,SACrD,CAAA,CAAA;AAAA,OACF,CAAA,CAAA;AAAA,KACH,CAAA;AAAA,GAAA;AAAA,EAdA,iBAAiB,KAA8B,EAAA;AAC7C,IAAQ,OAAA,CAAA,KAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,KAAA,CAAO,iBAAe,KAAO,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,KAAA,CAAA,eAAA,CAAA,CAAA;AAAA,GACvC;AAAA,EAcA,MAAM,cACJ,CAAA,UAAA,EACA,UACuB,EAAA;AACvB,IAAA,OAAO,IAAI,OAAA,CAAsB,OAAO,OAAA,EAAS,MAAW,KAAA;AAC1D,MAAM,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,iBAAkB,EAAA,CAAA;AAE9C,MAAA,IAAI,EAAE,QAAoB,YAAAC,eAAA,CAAA;AACxB,QAAO,OAAA,MAAA,CAAO,KAAM,CAAA,2BAA2B,CAAC,CAAA,CAAA;AAElD,MAAA,IAAI,KAAsB,GAAA;AAAA,QACxB,aAAa,QAAS,CAAA,WAAA;AAAA,QACtB,iBAAiB,QAAS,CAAA,eAAA;AAAA,QAC1B,cAAc,QAAS,CAAA,YAAA;AAAA,OACzB,CAAA;AAEA,MAAI,IAAA,CAAC,IAAK,CAAA,gBAAA,CAAiB,KAAK,CAAA;AAC9B,QAAO,OAAA,MAAA,CAAO,KAAM,CAAA,gCAAgC,CAAC,CAAA,CAAA;AACvD,MAAA,IAAI,CAAC,UAAA;AAAY,QAAA,OAAO,QAAQ,KAAK,CAAA,CAAA;AAErC,MAAI,IAAA;AACF,QAAA,MAAM,MAA0C,GAAA;AAAA,UAC9C,OAAS,EAAA,UAAA;AAAA,UACT,eAAiB,EAAA,iBAAA;AAAA,SACnB,CAAA;AACA,QAAI,IAAA,UAAA;AAAY,UAAA,MAAA,CAAO,UAAa,GAAA,UAAA,CAAA;AAEpC,QAAM,MAAA,WAAA,GAAc,MAAM,IAAID,uBAAA,CAAI,KAAM,CAAA,UAAA,CAAW,MAAM,CAAA,CAAE,OAAQ,EAAA,CAAA;AAEnE,QAAI,IAAA,CAAC,YAAY,WAAa,EAAA;AAC5B,UAAM,MAAA,IAAI,KAAM,CAAA,CAAA,iCAAA,EAAoC,UAAY,CAAA,CAAA,CAAA,CAAA;AAAA,SAClE;AAEA,QAAQ,KAAA,GAAA;AAAA,UACN,WAAA,EAAa,YAAY,WAAY,CAAA,WAAA;AAAA,UACrC,eAAA,EAAiB,YAAY,WAAY,CAAA,eAAA;AAAA,UACzC,YAAA,EAAc,YAAY,WAAY,CAAA,YAAA;AAAA,SACxC,CAAA;AAAA,eACO,CAAP,EAAA;AACA,QAAQ,OAAA,CAAA,IAAA,CAAK,yCAAyC,CAAG,CAAA,CAAA,CAAA,CAAA;AACzD,QAAA,OAAO,MAAO,CAAA,KAAA,CAAM,CAA0B,uBAAA,EAAA,CAAA,CAAA,CAAG,CAAC,CAAA,CAAA;AAAA,OACpD;AACA,MAAA,OAAO,QAAQ,KAAK,CAAA,CAAA;AAAA,KACrB,CAAA,CAAA;AAAA,GACH;AAAA,EACA,MAAM,cAAA,CACJ,WACA,EAAA,UAAA,EACA,UACiB,EAAA;AACjB,IAAA,MAAM,WAAc,GAAA,MAAM,IAAK,CAAA,cAAA,CAAe,YAAY,UAAU,CAAA,CAAA;AAEpE,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,IAAM,EAAA,CAAA,iBAAA,CAAA;AAAA,MACN,IAAM,EAAA,CAAA,8DAAA,CAAA;AAAA,MACN,OAAS,EAAA;AAAA,QACP,cAAgB,EAAA,WAAA;AAAA,OAClB;AAAA,MACA,SAAW,EAAA,IAAA;AAAA,KACb,CAAA;AAEA,IAAM,MAAA,MAAA,GAASE,SAAK,CAAA,OAAA,EAAS,WAAW,CAAA,CAAA;AACxC,IAAA,MAAM,GAAM,GAAA,CAAA,QAAA,EAAW,MAAO,CAAA,IAAA,CAAA,EAAO,MAAO,CAAA,IAAA,CAAA,CAAA,CAAA;AAC5C,IAAA,MAAM,YAAY,MAAO,CAAA,IAAA,CAAK,KAAK,QAAQ,CAAA,CAAE,SAAS,QAAQ,CAAA,CAAA;AAC9D,IAAA,MAAM,gBAAmB,GAAA,SAAA,CACtB,OAAQ,CAAA,KAAA,EAAO,GAAG,CAAA,CAClB,OAAQ,CAAA,KAAA,EAAO,GAAG,CAAA,CAClB,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAA,CAAA;AAEpB,IAAA,OAAO,CAAc,WAAA,EAAA,gBAAA,CAAA,CAAA,CAAA;AAAA,GACvB;AAAA,EAEA,MAAM,+BACJ,cAC4B,EAAA;AAC5B,IAAA,MAAM,8BAAiD,MAAO,CAAA,MAAA;AAAA,MAC5D,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AAEA,IAA4B,2BAAA,CAAA,mBAAA,GAAsB,MAAM,IAAK,CAAA,cAAA;AAAA,MAC3D,cAAe,CAAA,IAAA;AAAA,MACf,cAAe,CAAA,UAAA;AAAA,MACf,cAAe,CAAA,UAAA;AAAA,KACjB,CAAA;AACA,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AACF;;ACnHA,MAAM,QAAW,GAAA,+CAAA,CAAA;AAMV,MAAM,qCAEb,CAAA;AAAA,EAIE,WACmB,CAAA,MAAA,EACA,eAAmC,GAAA,IAAIC,iCACxD,EAAA;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA,CAAA;AALnB,IAAA,IAAA,CAAQ,WAA2B,GAAA,EAAE,KAAO,EAAA,EAAA,EAAI,oBAAoB,CAAE,EAAA,CAAA;AAAA,GAMnE;AAAA,EAEH,MAAM,+BACJ,cAC8B,EAAA;AAC9B,IAAA,MAAM,8BAAmD,MAAO,CAAA,MAAA;AAAA,MAC9D,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AAEA,IAA4B,2BAAA,CAAA,mBAAA,GAAsB,MAAM,IAAA,CAAK,QAAS,EAAA,CAAA;AACtE,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAc,QAA4B,GAAA;AACxC,IAAI,IAAA,CAAC,IAAK,CAAA,oBAAA,EAAwB,EAAA;AAChC,MAAA,OAAO,KAAK,WAAY,CAAA,KAAA,CAAA;AAAA,KAC1B;AAEA,IAAI,IAAA,CAAC,KAAK,eAAiB,EAAA;AACzB,MAAK,IAAA,CAAA,eAAA,GAAkB,KAAK,aAAc,EAAA,CAAA;AAAA,KAC5C;AAEA,IAAA,OAAO,IAAK,CAAA,eAAA,CAAA;AAAA,GACd;AAAA,EAEA,MAAc,aAAiC,GAAA;AAC7C,IAAI,IAAA;AACF,MAAK,IAAA,CAAA,MAAA,CAAO,KAAK,kCAAkC,CAAA,CAAA;AAEnD,MAAA,MAAM,cAAiB,GAAA,MAAM,IAAK,CAAA,eAAA,CAAgB,SAAS,QAAU,EAAA;AAAA,QACnE,cAAA,EAAgB,EAAE,OAAA,EAAS,GAAO,EAAA;AAAA;AAAA,OACnC,CAAA,CAAA;AACD,MAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,QAAM,MAAA,IAAI,MAAM,qBAAqB,CAAA,CAAA;AAAA,OACvC;AAEA,MAAA,IAAA,CAAK,WAAc,GAAA,cAAA,CAAA;AAAA,aACZ,GAAP,EAAA;AACA,MAAK,IAAA,CAAA,MAAA,CAAO,KAAM,CAAA,6BAAA,EAA+B,GAAG,CAAA,CAAA;AAGpD,MAAI,IAAA,IAAA,CAAK,cAAgB,EAAA;AACvB,QAAM,MAAA,GAAA,CAAA;AAAA,OACR;AAAA,KACF;AAEA,IAAA,IAAA,CAAK,eAAkB,GAAA,KAAA,CAAA,CAAA;AACvB,IAAA,OAAO,KAAK,WAAY,CAAA,KAAA,CAAA;AAAA,GAC1B;AAAA,EAEQ,oBAAgC,GAAA;AAEtC,IAAA,MAAM,SAAY,GAAA,IAAA,CAAK,WAAY,CAAA,kBAAA,GAAqB,KAAK,EAAK,GAAA,GAAA,CAAA;AAClE,IAAO,OAAA,IAAA,CAAK,KAAS,IAAA,SAAA,CAAA;AAAA,GACvB;AAAA,EAEQ,YAAwB,GAAA;AAC9B,IAAA,OAAO,IAAK,CAAA,GAAA,EAAS,IAAA,IAAA,CAAK,WAAY,CAAA,kBAAA,CAAA;AAAA,GACxC;AACF;;AC5EO,MAAM,8BAEb,CAAA;AAAA,EACE,MAAM,8BACJ,CAAA,cAAA,EACA,UAC4B,EAAA;AAC5B,IAAA,MAAM,8BAAiD,MAAO,CAAA,MAAA;AAAA,MAC5D,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AACA,IAAA,MAAM,YAAgC,UAAW,CAAA,MAAA,CAAA;AAEjD,IAAA,IAAI,SAAW,EAAA;AACb,MAAA,2BAAA,CAA4B,mBAAsB,GAAA,SAAA,CAAA;AAAA,KAC7C,MAAA;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,0DAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AACF;;ACvBO,MAAM,kCAEb,CAAA;AAAA,EACE,MAAM,+BACJ,cAC4B,EAAA;AAC5B,IAAA,MAAM,8BAAiD,MAAO,CAAA,MAAA;AAAA,MAC5D,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AACA,IAAA,MAAM,MAAS,GAAA,IAAIC,oBAAU,CAAA,EAAA,CAAG,oBAAqB,EAAA,CAAA;AACrD,IAAA,MAAM,WAAc,GAAA,MAAM,MAAO,CAAA,IAAA,CAAK,cAAe,EAAA,CAAA;AAErD,IAAA,IAAI,WAAa,EAAA;AACf,MAAA,2BAAA,CAA4B,mBAAsB,GAAA,WAAA,CAAA;AAAA,KAC7C,MAAA;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,sFAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AACF;;ACtBO,MAAM,4BAAiE,CAAA;AAAA,EAC5E,MAAM,+BACJ,cACuC,EAAA;AACvC,IAAO,OAAA,cAAA,CAAA;AAAA,GACT;AACF;;ACLO,MAAM,4BAAiE,CAAA;AAAA,EAC5E,MAAM,8BACJ,CAAA,cAAA,EACA,UACyB,EAAA;AA5B7B,IAAA,IAAA,EAAA,CAAA;AA6BI,IAAA,MAAM,8BAA8C,MAAO,CAAA,MAAA;AAAA,MACzD,EAAC;AAAA,MACD,cAAA;AAAA,KACF,CAAA;AAEA,IAAM,MAAA,EAAE,mBAAsB,GAAA,cAAA,CAAA;AAE9B,IAAI,IAAA,CAAC,iBAAqB,IAAA,iBAAA,KAAsB,EAAI,EAAA;AAClD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,yDAAA,CAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAM,MAAA,SAAA,GAAA,CAAgC,EAAW,GAAA,UAAA,CAAA,IAAA,KAAX,IAAkB,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,iBAAA,CAAA,CAAA;AAExD,IAAA,IAAI,SAAW,EAAA;AACb,MAAA,2BAAA,CAA4B,mBAAsB,GAAA,SAAA,CAAA;AAAA,KAC7C,MAAA;AACL,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAmC,gCAAA,EAAA,iBAAA,CAAA,gBAAA,CAAA;AAAA,OACrC,CAAA;AAAA,KACF;AACA,IAAO,OAAA,2BAAA,CAAA;AAAA,GACT;AACF;;ACxBO,MAAM,iCAAkC,CAAA;AAAA,EAC7C,OAAO,mCACL,CAAA,YAAA,EACA,OAG0B,EAAA;AAC1B,IAAA,QAAQ,YAAc;AAAA,MACpB,KAAK,QAAU,EAAA;AACb,QAAA,OAAO,IAAI,8BAA+B,EAAA,CAAA;AAAA,OAC5C;AAAA,MACA,KAAK,KAAO,EAAA;AACV,QAAA,OAAO,IAAI,8BAA+B,EAAA,CAAA;AAAA,OAC5C;AAAA,MACA,KAAK,OAAS,EAAA;AACZ,QAAO,OAAA,IAAI,qCAAsC,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA,OACjE;AAAA,MACA,KAAK,gBAAkB,EAAA;AACrB,QAAA,OAAO,IAAI,4BAA6B,EAAA,CAAA;AAAA,OAC1C;AAAA,MACA,KAAK,sBAAwB,EAAA;AAC3B,QAAA,OAAO,IAAI,kCAAmC,EAAA,CAAA;AAAA,OAChD;AAAA,MACA,KAAK,MAAQ,EAAA;AACX,QAAA,OAAO,IAAI,4BAA6B,EAAA,CAAA;AAAA,OAC1C;AAAA,MACA,KAAK,mBAAqB,EAAA;AACxB,QAAA,OAAO,IAAI,4BAA6B,EAAA,CAAA;AAAA,OAC1C;AAAA,MACA,SAAS;AACP,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAiB,cAAA,EAAA,YAAA,CAAA,oDAAA,CAAA;AAAA,SACnB,CAAA;AAAA,OACF;AAAA,KACF;AAAA,GACF;AACF;;AC9CO,MAAM,oBAA2D,CAAA;AAAA,EAGtE,YAAY,cAAkC,EAAA;AAC5C,IAAA,IAAA,CAAK,cAAiB,GAAA,cAAA,CAAA;AAAA,GACxB;AAAA,EAEA,OAAO,WAAW,MAAsC,EAAA;AAGtD,IAAA,OAAO,IAAI,oBAAA;AAAA,MACT,MAAO,CAAA,cAAA,CAAe,UAAU,CAAA,CAAE,IAAI,CAAK,CAAA,KAAA;AA9BjD,QAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AA+BQ,QAAM,MAAA,YAAA,GAAe,CAAE,CAAA,SAAA,CAAU,cAAc,CAAA,CAAA;AAC/C,QAAA,MAAM,cAAiC,GAAA;AAAA,UACrC,IAAA,EAAM,CAAE,CAAA,SAAA,CAAU,MAAM,CAAA;AAAA,UACxB,GAAA,EAAK,CAAE,CAAA,SAAA,CAAU,KAAK,CAAA;AAAA,UACtB,mBAAA,EAAqB,CAAE,CAAA,iBAAA,CAAkB,qBAAqB,CAAA;AAAA,UAC9D,aAAe,EAAA,CAAA,EAAA,GAAA,CAAA,CAAE,kBAAmB,CAAA,eAAe,MAApC,IAAyC,GAAA,EAAA,GAAA,KAAA;AAAA,UACxD,iBAAmB,EAAA,CAAA,EAAA,GAAA,CAAA,CAAE,kBAAmB,CAAA,mBAAmB,MAAxC,IAA6C,GAAA,EAAA,GAAA,KAAA;AAAA,UAChE,MAAA,EAAQ,CAAE,CAAA,iBAAA,CAAkB,QAAQ,CAAA;AAAA,UACpC,MAAA,EAAQ,CAAE,CAAA,iBAAA,CAAkB,QAAQ,CAAA;AAAA,UACpC,YAAA;AAAA,SACF,CAAA;AACA,QAAM,MAAA,YAAA,GAAe,CAAE,CAAA,iBAAA,CAAkB,cAAc,CAAA,CAAA;AACvD,QAAA,IAAI,YAAc,EAAA;AAChB,UAAA,cAAA,CAAe,YAAe,GAAA,YAAA,CAAA;AAAA,SAChC;AACA,QAAM,MAAA,YAAA,GAAe,CAAE,CAAA,iBAAA,CAAkB,cAAc,CAAA,CAAA;AACvD,QAAA,IAAI,YAAc,EAAA;AAChB,UAAA,cAAA,CAAe,YAAe,GAAA,YAAA,CAAA;AAAA,SAChC;AACA,QAAI,IAAA,CAAA,CAAE,GAAI,CAAA,qBAAqB,CAAG,EAAA;AAChC,UAAe,cAAA,CAAA,mBAAA,GAAsB,CAAE,CAAA,GAAA,CAAI,qBAAqB,CAAA,CAAA;AAAA,SAClE;AAEA,QAAA,QAAQ,YAAc;AAAA,UACpB,KAAK,QAAU,EAAA;AACb,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAAA,UACA,KAAK,KAAO,EAAA;AACV,YAAM,MAAA,UAAA,GAAa,CAAE,CAAA,iBAAA,CAAkB,YAAY,CAAA,CAAA;AACnD,YAAM,MAAA,UAAA,GAAa,CAAE,CAAA,iBAAA,CAAkB,YAAY,CAAA,CAAA;AAEnD,YAAA,OAAO,EAAE,UAAA,EAAY,UAAY,EAAA,GAAG,cAAe,EAAA,CAAA;AAAA,WACrD;AAAA,UACA,KAAK,OAAS,EAAA;AACZ,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAAA,UACA,KAAK,MAAQ,EAAA;AACX,YAAM,MAAA,iBAAA,GAAoB,CAAE,CAAA,SAAA,CAAU,mBAAmB,CAAA,CAAA;AAEzD,YAAO,OAAA,EAAE,iBAAmB,EAAA,GAAG,cAAe,EAAA,CAAA;AAAA,WAChD;AAAA,UACA,KAAK,gBAAkB,EAAA;AACrB,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAAA,UACA,KAAK,sBAAwB,EAAA;AAC3B,YAAO,OAAA,cAAA,CAAA;AAAA,WACT;AAAA,UACA,SAAS;AACP,YAAA,MAAM,IAAI,KAAA;AAAA,cACR,CAAiB,cAAA,EAAA,YAAA,CAAA,kCAAA,CAAA;AAAA,aACnB,CAAA;AAAA,WACF;AAAA,SACF;AAAA,OACD,CAAA;AAAA,KACH,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,WAAyC,GAAA;AAC7C,IAAA,OAAO,IAAK,CAAA,cAAA,CAAA;AAAA,GACd;AACF;;ACjEgB,SAAA,eAAA,CAAgB,IAAe,OAA6B,EAAA;AAC1E,EAAI,IAAA,MAAA,CAAA;AACJ,EAAA,IAAI,SAAY,GAAA,KAAA,CAAA;AAChB,EAAM,MAAA,mBAAA,GAAsB,IAAI,OAAA,CAAc,CAAW,OAAA,KAAA;AACvD,IAAA,MAAA,GAAS,MAAM;AACb,MAAQ,OAAA,EAAA,CAAA;AACR,MAAY,SAAA,GAAA,IAAA,CAAA;AAAA,KACd,CAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,MAAM,eAAe,YAAY;AAC/B,IAAA,OAAO,CAAC,SAAW,EAAA;AACjB,MAAI,IAAA;AACF,QAAA,MAAM,EAAG,EAAA,CAAA;AAAA,OACT,CAAA,MAAA;AAAA,OAEF;AAEA,MAAA,MAAM,QAAQ,IAAK,CAAA;AAAA,QACjB,IAAI,OAAQ,CAAA,CAAA,OAAA,KAAW,UAAW,CAAA,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,QACnD,mBAAA;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,GACF,CAAA;AACA,EAAa,YAAA,EAAA,CAAA;AAEb,EAAO,OAAA,MAAA,CAAA;AACT;;ACZO,MAAM,iBAAwD,CAAA;AAAA,EACnE,YACmB,OACA,EAAA,MAAA,EACT,cAAkD,GAAA,KAAA,CAAA,EAClD,oBAA6B,KACrC,EAAA;AAJiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA,CAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACT,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA,CAAA;AACA,IAAA,IAAA,CAAA,iBAAA,GAAA,iBAAA,CAAA;AAAA,GACP;AAAA,EAEH,OAAO,oBAAA,CACL,MACA,EAAA,MAAA,EACA,eACmB,EAAA;AArDvB,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AAsDI,IAAA,MAAM,0BACJ,EAAO,GAAA,CAAA,EAAA,GAAA,MAAA,CAAA,sBAAA,CAAuB,wBAAwB,CAAtD,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAyD,IAAI,CAAO,GAAA,KAAA;AAClE,MAAO,OAAA,EAAE,GAAK,EAAA,GAAA,CAAI,SAAU,CAAA,KAAK,GAAG,KAAO,EAAA,GAAA,CAAI,SAAU,CAAA,OAAO,CAAE,EAAA,CAAA;AAAA,KACpE,CAAA,KAFA,YAEM,EAAC,CAAA;AAET,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,SAAA,EAAW,MAAO,CAAA,SAAA,CAAU,WAAW,CAAA;AAAA,MACvC,MAAQ,EAAA,CAAA,EAAA,GAAA,MAAA,CAAO,iBAAkB,CAAA,QAAQ,MAAjC,IAAsC,GAAA,EAAA,GAAA,GAAA;AAAA,MAC9C,aAAe,EAAA,CAAA,EAAA,GAAA,MAAA,CAAO,kBAAmB,CAAA,eAAe,MAAzC,IAA8C,GAAA,EAAA,GAAA,KAAA;AAAA,MAC7D,iBACE,EAAA,CAAA,EAAA,GAAA,MAAA,CAAO,kBAAmB,CAAA,mBAAmB,MAA7C,IAAkD,GAAA,EAAA,GAAA,KAAA;AAAA,MACpD,eAAiB,EAAA,CAAA,EAAA,GAAA,MAAA,CAAO,kBAAmB,CAAA,iBAAiB,MAA3C,IAAgD,GAAA,EAAA,GAAA,KAAA;AAAA,MACjE,sBAAA;AAAA,KACF,CAAA;AACA,IAAA,MAAM,iBAAoB,GAAA,IAAI,iBAAkB,CAAA,OAAA,EAAS,MAAM,CAAA,CAAA;AAC/D,IAAA,IAAI,eAAiB,EAAA;AACnB,MAAA,eAAA;AAAA,QACE,MAAM,kBAAkB,eAAgB,EAAA;AAAA,QACxC,gBAAgB,QAAS,EAAA;AAAA,OAC3B,CAAA;AAAA,KACF;AACA,IAAO,OAAA,iBAAA,CAAA;AAAA,GACT;AAAA,EAEA,OAAO,UAAA,CACL,MACA,EAAA,eAAA,GAAwC,KACrB,CAAA,EAAA;AACnB,IAAA,OAAO,iBAAkB,CAAA,oBAAA;AAAA,MACvB,MAAA;AAAA,MACA,IAAIA,oBAAU,CAAA,EAAA,CAAG,oBAAqB,EAAA;AAAA,MACtC,eAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,WAAyC,GAAA;AAzFjD,IAAA,IAAA,EAAA,CAAA;AA0FI,IAAI,IAAA,CAAC,KAAK,iBAAmB,EAAA;AAE3B,MAAA,MAAM,KAAK,eAAgB,EAAA,CAAA;AAAA,KAC7B;AACA,IAAO,OAAA,CAAA,EAAA,GAAA,IAAA,CAAK,cAAL,KAAA,IAAA,GAAA,EAAA,GAAuB,EAAC,CAAA;AAAA,GACjC;AAAA;AAAA,EAGA,MAAM,eAAiC,GAAA;AAlGzC,IAAA,IAAA,EAAA,CAAA;AAmGI,IAAM,MAAA;AAAA,MACJ,SAAA;AAAA,MACA,MAAA;AAAA,MACA,aAAA;AAAA,MACA,iBAAA;AAAA,MACA,eAAA;AAAA,MACA,sBAAA;AAAA,QACE,IAAK,CAAA,OAAA,CAAA;AACT,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,MAAA,EAAQ,YAAY,SAAuB,CAAA,WAAA,EAAA,MAAA,CAAA,CAAA;AAAA,KAC7C,CAAA;AAEA,IAAI,IAAA;AACF,MAAA,MAAM,CAAC,QAAQ,CAAA,GAAI,MAAM,IAAK,CAAA,MAAA,CAAO,aAAa,OAAO,CAAA,CAAA;AACzD,MAAA,IAAA,CAAK,mBAAkB,EAAS,GAAA,QAAA,CAAA,QAAA,KAAT,YAAqB,EAAC,EAC1C,OAAO,CAAK,CAAA,KAAA;AACX,QAAO,OAAA,sBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,sBAAA,CAAwB,MAAM,CAAO,GAAA,KAAA;AAC1C,UAAI,IAAA,CAAC,EAAE,cAAgB,EAAA;AACrB,YAAO,OAAA,KAAA,CAAA;AAAA,WACT;AACA,UAAA,OAAO,CAAE,CAAA,cAAA,CAAe,GAAI,CAAA,GAAG,MAAM,GAAI,CAAA,KAAA,CAAA;AAAA,SAC3C,CAAA,CAAA;AAAA,OACD,CACA,CAAA,GAAA,CAAI,CAAE,CAAA,KAAA;AA1Hf,QAAA,IAAAC,GAAA,EAAA,EAAA,CAAA;AA0HmB,QAAA,OAAA;AAAA;AAAA,UAET,IAAMA,EAAAA,CAAAA,GAAAA,GAAA,CAAE,CAAA,IAAA,KAAF,OAAAA,GAAU,GAAA,SAAA;AAAA,UAChB,GAAK,EAAA,CAAA,QAAA,EAAA,CAAW,EAAE,GAAA,CAAA,CAAA,QAAA,KAAF,IAAc,GAAA,EAAA,GAAA,EAAA,CAAA,CAAA;AAAA,UAC9B,YAAc,EAAA,QAAA;AAAA,UACd,aAAA;AAAA,UACA,iBAAA;AAAA,UACA,GAAI,eACA,GAAA;AAAA,YACE,YAAc,EAAA,KAAA;AAAA,YACd,mBAAqB,EAAA;AAAA,cACnB,SAAA;AAAA,cACA,MAAA;AAAA,cACA,aAAa,CAAE,CAAA,IAAA;AAAA,aACjB;AAAA,cAEF,EAAC;AAAA,SACP,CAAA;AAAA,OAAE,CAAA,CAAA;AACJ,MAAA,IAAA,CAAK,iBAAoB,GAAA,IAAA,CAAA;AAAA,aAClB,CAAP,EAAA;AACA,MAAA,MAAM,IAAIC,qBAAA;AAAA,QACR,iEAAiE,SAAoB,CAAA,QAAA,EAAA,MAAA,CAAA,CAAA;AAAA,QACrF,CAAA;AAAA,OACF,CAAA;AAAA,KACF;AAAA,GACF;AACF;;ACvHO,MAAM,qBAA4D,CAAA;AAAA,EAGvE,YAAY,aAA2B,EAAA;AACrC,IAAA,IAAA,CAAK,aAAgB,GAAA,aAAA,CAAA;AAAA,GACvB;AAAA,EAEA,OAAO,WAAW,UAA+C,EAAA;AAC/D,IAAO,OAAA,IAAI,sBAAsB,UAAU,CAAA,CAAA;AAAA,GAC7C;AAAA,EAEA,MAAM,WAAyC,GAAA;AAC7C,IAAA,MAAM,eAAe,CAAwB,qBAAA,EAAAC,uDAAA,CAAA,CAAA,CAAA;AAC7C,IAAA,MAAM,iBAAiB,CAAwB,qBAAA,EAAAC,0DAAA,CAAA,CAAA,CAAA;AAC/C,IAAA,MAAM,kBAAkB,CAAwB,qBAAA,EAAAC,0DAAA,CAAA,CAAA,CAAA;AAEhD,IAAA,MAAM,MAA0C,GAAA;AAAA,MAC9C,IAAM,EAAA,UAAA;AAAA,MACN,WAAa,EAAA,oBAAA;AAAA,MACb,CAAC,YAAY,GAAGC,mCAAA;AAAA,MAChB,CAAC,cAAc,GAAGA,mCAAA;AAAA,MAClB,CAAC,eAAe,GAAGA,mCAAA;AAAA,KACrB,CAAA;AAEA,IAAA,MAAM,QAAW,GAAA,MAAM,IAAK,CAAA,aAAA,CAAc,WAAY,CAAA;AAAA,MACpD,MAAA,EAAQ,CAAC,MAAM,CAAA;AAAA,KAChB,CAAA,CAAA;AACD,IAAO,OAAA,QAAA,CAAS,KAAM,CAAA,GAAA,CAAI,CAAU,MAAA,KAAA;AAClC,MAAA,MAAM,cAAiC,GAAA;AAAA,QACrC,IAAA,EAAM,OAAO,QAAS,CAAA,IAAA;AAAA,QACtB,GAAK,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaH,uDAAgC,CAAA;AAAA,QAClE,MACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaC,0DAAmC,CAAA;AAAA,QAClE,YACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaC,0DAAmC,CAAA;AAAA,QAClE,iBACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CACdE,gEACF,CAAA;AAAA,QACF,mBACE,MAAO,CAAA,QAAA,CAAS,YACdC,gEACF,CAAA,KAAO,SACH,IACA,GAAA,KAAA;AAAA,QACN,eACE,MAAO,CAAA,QAAA,CAAS,YACdC,4DACF,CAAA,KAAO,SACH,IACA,GAAA,KAAA;AAAA,QACN,YACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaC,0DAAmC,CAAA;AAAA,QAClE,YACE,EAAA,MAAA,CAAO,QAAS,CAAA,WAAA,CAAaC,0DAAmC,CAAA;AAAA,OACpE,CAAA;AAEA,MAAO,OAAA,cAAA,CAAA;AAAA,KACR,CAAA,CAAA;AAAA,GACH;AACF;;ACvEO,MAAM,+BAEb,CAAA;AAAA,EAGS,WAAc,GAAA;AACnB,IAAA,IAAA,CAAK,cAAiB,GAAA;AAAA,MACpB;AAAA,QACE,IAAM,EAAA,OAAA;AAAA,QACN,GAAK,EAAA,sBAAA;AAAA,QACL,YAAc,EAAA,mBAAA;AAAA,QACd,iBAAmB,EAAA,IAAA;AAAA,OACrB;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,WAAyC,GAAA;AAC7C,IAAA,OAAO,IAAK,CAAA,cAAA,CAAA;AAAA,GACd;AACF;;ACZA,MAAM,wBAA+D,CAAA;AAAA,EACnE,YAAqB,gBAAgD,EAAA;AAAhD,IAAA,IAAA,CAAA,gBAAA,GAAA,gBAAA,CAAA;AAAA,GAAiD;AAAA,EAEtE,MAAM,WAAyC,GAAA;AAC7C,IAAA,OAAO,MAAM,OAAQ,CAAA,GAAA;AAAA,MACnB,KAAK,gBAAiB,CAAA,GAAA,CAAI,CAAY,QAAA,KAAA,QAAA,CAAS,aAAa,CAAA;AAAA,KAC9D,CACG,KAAK,CAAO,GAAA,KAAA;AACX,MAAA,OAAO,IAAI,IAAK,EAAA,CAAA;AAAA,KACjB,CACA,CAAA,KAAA,CAAM,CAAK,CAAA,KAAA;AACV,MAAM,MAAA,CAAA,CAAA;AAAA,KACP,CAAA,CAAA;AAAA,GACL;AACF,CAAA;AAEO,MAAM,0BAA6B,GAAA,CACxC,UACA,EAAA,aAAA,EACA,kBAAwC,KACT,CAAA,KAAA;AAC/B,EAAA,MAAM,mBAAmB,UACtB,CAAA,cAAA,CAAe,kCAAkC,CAAA,CACjD,IAAI,CAAwB,oBAAA,KAAA;AAC3B,IAAM,MAAA,IAAA,GAAO,oBAAqB,CAAA,SAAA,CAAU,MAAM,CAAA,CAAA;AAClD,IAAA,QAAQ,IAAM;AAAA,MACZ,KAAK,SAAA;AACH,QAAO,OAAA,qBAAA,CAAsB,WAAW,aAAa,CAAA,CAAA;AAAA,MACvD,KAAK,mBAAA;AACH,QAAA,OAAO,IAAI,+BAAgC,EAAA,CAAA;AAAA,MAC7C,KAAK,QAAA;AACH,QAAO,OAAA,oBAAA,CAAqB,WAAW,oBAAoB,CAAA,CAAA;AAAA,MAC7D,KAAK,KAAA;AACH,QAAA,OAAO,iBAAkB,CAAA,UAAA;AAAA,UACvB,oBAAA;AAAA,UACA,eAAA;AAAA,SACF,CAAA;AAAA,MACF;AACE,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAkD,+CAAA,EAAA,IAAA,CAAA,CAAA,CAAA;AAAA,SACpD,CAAA;AAAA,KACJ;AAAA,GACD,CAAA,CAAA;AAEH,EAAO,OAAA,IAAI,yBAAyB,gBAAgB,CAAA,CAAA;AACtD,CAAA;;AC5CO,MAAM,yBAA4B,GAAA,CACvC,MACA,EAAA,UAAA,EACA,eACG,KAAA;AACH,EAAM,MAAA,cAAA,GAAiB,OAAO,GAAsB,KAAA;AAClD,IAAM,MAAA,YAAA,GAAe,IAAI,IAAK,CAAA,SAAA,CAAA;AAC9B,IAAI,IAAA,YAAA,IAAgB,OAAO,YAAA,KAAiB,QAAU,EAAA;AACpD,MAAM,MAAA,IAAIC,kBAAW,CAA+B,6BAAA,CAAA,CAAA,CAAA;AAAA,KACtD,MAAA,IAAW,CAAC,YAAc,EAAA;AACxB,MAAM,MAAA,IAAIA,kBAAW,4BAA4B,CAAA,CAAA;AAAA,KACnD;AACA,IAAA,IAAI,SAA2C,GAAA,KAAA,CAAA,CAAA;AAE/C,IAAI,IAAA;AACF,MAAA,SAAA,GAAYC,4BAAe,YAAY,CAAA,CAAA;AAAA,aAChC,KAAP,EAAA;AACA,MAAM,MAAA,IAAID,iBAAW,CAAA,CAAA,oBAAA,EAAuB,KAAO,CAAA,CAAA,CAAA,CAAA;AAAA,KACrD;AAEA,IAAA,MAAM,KAAQ,GAAAE,oDAAA;AAAA,MACZ,IAAI,OAAQ,CAAA,aAAA;AAAA,KACd,CAAA;AAEA,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAM,MAAA,IAAIC,2BAAoB,oBAAoB,CAAA,CAAA;AAAA,KACpD;AAEA,IAAA,MAAM,MAAS,GAAA,MAAM,UAAW,CAAA,cAAA,CAAe,SAAW,EAAA;AAAA,MACxD,KAAA;AAAA,KACD,CAAA,CAAA;AAED,IAAA,IAAI,CAAC,MAAQ,EAAA;AACX,MAAA,MAAM,IAAIH,iBAAA;AAAA,QACR,CAAA,oBAAA,EAAuBI,gCAAmB,SAAS,CAAA,CAAA,CAAA;AAAA,OACrD,CAAA;AAAA,KACF;AACA,IAAO,OAAA,MAAA,CAAA;AAAA,GACT,CAAA;AAEA,EAAA,MAAA,CAAO,IAAK,CAAA,4BAAA,EAA8B,OAAO,GAAA,EAAK,GAAQ,KAAA;AAC5D,IAAM,MAAA,MAAA,GAAS,MAAM,cAAA,CAAe,GAAG,CAAA,CAAA;AACvC,IAAM,MAAA,QAAA,GAAW,MAAM,eAAA,CAAgB,4BAA6B,CAAA;AAAA,MAClE,MAAA;AAAA,MACA,IAAA,EAAM,IAAI,IAAK,CAAA,IAAA;AAAA,KAChB,CAAA,CAAA;AACD,IAAA,GAAA,CAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,GAClB,CAAA,CAAA;AAED,EAAA,MAAA,CAAO,IAAK,CAAA,yBAAA,EAA2B,OAAO,GAAA,EAAK,GAAQ,KAAA;AACzD,IAAM,MAAA,MAAA,GAAS,MAAM,cAAA,CAAe,GAAG,CAAA,CAAA;AAEvC,IAAI,IAAA,CAAC,GAAI,CAAA,IAAA,CAAK,eAAiB,EAAA;AAC7B,MAAM,MAAA,IAAIJ,kBAAW,qCAAqC,CAAA,CAAA;AAAA,eACjD,CAAC,KAAA,CAAM,QAAQ,GAAI,CAAA,IAAA,CAAK,eAAe,CAAG,EAAA;AACnD,MAAM,MAAA,IAAIA,kBAAW,kCAAkC,CAAA,CAAA;AAAA,KAC9C,MAAA,IAAA,GAAA,CAAI,IAAK,CAAA,eAAA,CAAgB,WAAW,CAAG,EAAA;AAChD,MAAM,MAAA,IAAIA,kBAAW,uCAAuC,CAAA,CAAA;AAAA,KAC9D;AAEA,IAAM,MAAA,QAAA,GAAW,MAAM,eAAA,CAAgB,0BAA2B,CAAA;AAAA,MAChE,MAAA;AAAA,MACA,eAAA,EAAiB,IAAI,IAAK,CAAA,eAAA;AAAA,MAC1B,IAAA,EAAM,IAAI,IAAK,CAAA,IAAA;AAAA,KAChB,CAAA,CAAA;AACD,IAAA,GAAA,CAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,GAClB,CAAA,CAAA;AACH,CAAA;;ACnEO,MAAM,yBAA8D,CAAA;AAAA,EAGzE,YAAY,eAA6C,EAAA;AACvD,IAAA,IAAA,CAAK,eAAkB,GAAA,eAAA,CAAA;AAAA,GACzB;AAAA;AAAA,EAGA,mBAAA,CACE,SACA,eACyC,EAAA;AACzC,IAAO,OAAA,IAAA,CAAK,gBAAgB,WAAY,EAAA,CAAE,KAAK,CAAa,QAAA,MAAA,EAAE,UAAW,CAAA,CAAA,CAAA;AAAA,GAC3E;AACF;;ACeO,MAAM,eAAmC,GAAA;AAAA,EAC9C;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,MAAA;AAAA,IACR,UAAY,EAAA,MAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,UAAA;AAAA,IACR,UAAY,EAAA,UAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,YAAA;AAAA,IACR,UAAY,EAAA,YAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,EAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,aAAA;AAAA,IACR,UAAY,EAAA,aAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,aAAA;AAAA,IACR,UAAY,EAAA,aAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,aAAA;AAAA,IACR,UAAY,EAAA,aAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,aAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,0BAAA;AAAA,IACR,UAAY,EAAA,0BAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,OAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,MAAA;AAAA,IACR,UAAY,EAAA,MAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,OAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,UAAA;AAAA,IACR,UAAY,EAAA,UAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,mBAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,WAAA;AAAA,IACR,UAAY,EAAA,WAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,cAAA;AAAA,IACR,UAAY,EAAA,cAAA;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAO,EAAA,MAAA;AAAA,IACP,UAAY,EAAA,IAAA;AAAA,IACZ,MAAQ,EAAA,YAAA;AAAA,IACR,UAAY,EAAA,YAAA;AAAA,GACd;AACF,EAAA;AAOA,MAAM,kBAAqB,GAAA,CAAC,EAC1B,KAAA,EAAA,CAAG,IAAS,KAAA,MAAA,CAAA;AACd,MAAM,QAAA,GAAW,CAAC,GAAA,KAA2C,GAAQ,KAAA,KAAA,CAAA,CAAA;AAErE,MAAM,8BAAA,GAAiC,CACrC,KACoB,KAAA;AACpB,EAAA,OAAO,OAAO,KAAA,KAAU,QAAW,GAAA,KAAA,CAAM,UAAc,GAAA,KAAA,CAAA;AACzD,CAAA,CAAA;AAEA,MAAM,oBAAA,GAAuB,CAC3B,OAC+B,KAAA;AAC/B,EAAO,OAAA;AAAA,IACL,YAAA,EAAc,8BAA+B,CAAA,OAAA,CAAQ,YAAY,CAAA;AAAA,IACjE,YAAA,EAAc,8BAA+B,CAAA,OAAA,CAAQ,YAAY,CAAA;AAAA,IACjE,UAAA,EAAY,8BAA+B,CAAA,OAAA,CAAQ,UAAU,CAAA;AAAA,GAC/D,CAAA;AACF,CAAA,CAAA;AAEA,MAAM,qBAAA,GAAwB,CAC5B,SAC0B,KAAA;AAC1B,EAAO,OAAA;AAAA,IACL,WAAW,SAAU,CAAA,SAAA;AAAA,IACrB,QAAA,EAAU,oBAAqB,CAAA,SAAA,CAAU,QAAQ,CAAA;AAAA,IACjD,WAAA,EAAa,oBAAqB,CAAA,SAAA,CAAU,WAAW,CAAA;AAAA,GACzD,CAAA;AACF,CAAA,CAAA;AAEA,MAAM,sBAAA,GAAyB,CAC7B,UACsB,KAAA;AACtB,EAAO,OAAA,UAAA,CACJ,GAAI,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,SAAS,EACpB,IAAK,EAAA,CACL,GAAI,CAAA,CAAC,EAAmC,KAAA;AACvC,IAAO,OAAA;AAAA,MACL,KAAK,EAAG,CAAA,GAAA;AAAA,MACR,MAAA,EAAQ,oBAAqB,CAAA,EAAA,CAAG,MAAM,CAAA;AAAA,MACtC,GAAA,EAAK,oBAAqB,CAAA,EAAA,CAAG,GAAG,CAAA;AAAA,MAChC,UAAY,EAAA,EAAA,CAAG,UAAW,CAAA,GAAA,CAAI,qBAAqB,CAAA;AAAA,KACrD,CAAA;AAAA,GACD,CAAA,CAAA;AACL,CAAA,CAAA;AAIO,MAAM,uBAAwB,CAAA;AAAA,EAQnC,WAAY,CAAA;AAAA,IACV,MAAA;AAAA,IACA,OAAA;AAAA,IACA,cAAA;AAAA,IACA,eAAA;AAAA,IACA,kBAAqB,GAAA,eAAA;AAAA,GACY,EAAA;AACjC,IAAA,IAAA,CAAK,MAAS,GAAA,MAAA,CAAA;AACd,IAAA,IAAA,CAAK,OAAU,GAAA,OAAA,CAAA;AACf,IAAA,IAAA,CAAK,cAAiB,GAAA,cAAA,CAAA;AACtB,IAAA,IAAA,CAAK,eAAkB,GAAA,eAAA,CAAA;AACvB,IAAK,IAAA,CAAA,kBAAA,GAAqB,IAAI,GAAA,CAAI,kBAAkB,CAAA,CAAA;AACpD,IAAA,IAAA,CAAK,kBAAkB,EAAC,CAAA;AAAA,GAC1B;AAAA,EAEA,MAAM,0BAA2B,CAAA;AAAA,IAC/B,MAAA;AAAA,IACA,IAAA;AAAA,IACA,eAAA;AAAA,GAC4D,EAAA;AAE5D,IAAA,OAAO,IAAK,CAAA,cAAA;AAAA,MACV,MAAA;AAAA,MACA,IAAA;AAAA,0BACI,GAAmB,EAAA;AAAA,MACvB,eAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,MAAM,4BAA6B,CAAA;AAAA,IACjC,MAAA;AAAA,IACA,IAAA;AAAA,GAC8D,EAAA;AAC9D,IAAA,OAAO,IAAK,CAAA,cAAA,CAAe,MAAQ,EAAA,IAAA,EAAM,KAAK,kBAAkB,CAAA,CAAA;AAAA,GAClE;AAAA,EAEA,MAAc,cAAA,CACZ,MACA,EAAA,IAAA,EACA,oBACA,eACA,EAAA;AAxOJ,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AAyOI,IAAM,MAAA,UAAA,GAAA,CAAA,CACJ,kBAAO,QAAP,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAiB,gBAAjB,IAA+B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,4BAAA,CAAA,MAAA,CAC/B,EAAO,GAAA,MAAA,CAAA,QAAA,KAAP,IAAiB,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA,CAAA;AAEnB,IAAA,MAAM,8BACJ,GAAA,MAAM,IAAK,CAAA,8BAAA,CAA+B,QAAQ,IAAM,EAAA;AAAA,MACtD,kBAAA;AAAA,MACA,eAAA,EAAiB,4CAAmB,EAAC;AAAA,KACtC,CAAA,CAAA;AAEH,IAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,MACV,CAAA,qBAAA,EAAwB,8BAA8B,8BACnD,CAAA,GAAA,CAAI,OAAK,CAAE,CAAA,IAAI,CACf,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA,CAAA,CAAA;AAAA,KACd,CAAA;AAEA,IAAA,MAAM,kBACJ,EAAO,GAAA,CAAA,EAAA,GAAA,MAAA,CAAA,QAAA,KAAP,mBAAiB,WAAjB,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CACE,8CACG,CAA8B,2BAAA,EAAA,UAAA,CAAA,CAAA,CAAA;AAErC,IAAA,MAAM,SACJ,GAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,MAAA,CAAO,QAAP,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAiB,gBAAjB,IAA+B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,mCAAA,CAAA,CAAA;AAEjC,IAAA,OAAO,OAAQ,CAAA,GAAA;AAAA,MACb,8BAAA,CAA+B,IAAI,CAAsB,kBAAA,KAAA;AACvD,QAAO,OAAA,IAAA,CAAK,QACT,sBAAuB,CAAA;AAAA,UACtB,SAAW,EAAA,UAAA;AAAA,UACX,cAAgB,EAAA,kBAAA;AAAA,UAChB,kBAAA;AAAA,UACA,aAAA;AAAA,UACA,kBACE,eACA,IAAA,kBAAA,CAAmB,mBACnB,IAAK,CAAA,eAAA,EACL,IAAI,CAAM,CAAA,MAAA;AAAA,YACV,GAAG,CAAA;AAAA,YACH,UAAY,EAAA,iBAAA;AAAA,WACZ,CAAA,CAAA;AAAA,UACF,SAAA;AAAA,SACD,EACA,IAAK,CAAA,CAAA,MAAA,KAAU,KAAK,iBAAkB,CAAA,kBAAA,EAAoB,MAAM,CAAC,CACjE,CAAA,KAAA;AAAA,UACC,CAAC,CACC,KAAA,CAAA,CAAE,IAAS,KAAA,YAAA,GACP,QAAQ,OAAQ,CAAA;AAAA,YACd;AAAA,cACE,MAAQ,EAAA;AAAA,gBACN,EAAE,SAAA,EAAW,aAAe,EAAA,OAAA,EAAS,EAAE,OAAQ,EAAA;AAAA,eACjD;AAAA,cACA,WAAW,EAAC;AAAA,aACd;AAAA,YACA,EAAC;AAAA,WACF,CAAA,GACD,OAAQ,CAAA,MAAA,CAAO,CAAC,CAAA;AAAA,UAEvB,IAAK,CAAA,CAAA,CAAA,KAAK,KAAK,gBAAiB,CAAA,kBAAA,EAAoB,CAAC,CAAC,CAAA,CAAA;AAAA,OAC1D,CAAA;AAAA,KACH,CAAE,IAAK,CAAA,IAAA,CAAK,yBAAyB,CAAA,CAAA;AAAA,GACvC;AAAA,EAEA,MAAc,8BAAA,CACZ,MACA,EAAA,IAAA,EACA,cACA,EAAA;AACA,IAAM,MAAA,cAAA,GAAmC,OACvC,MAAM,IAAA,CAAK,eAAe,mBAAoB,CAAA,MAAA,EAAQ,cAAc,CACpE,EAAA,QAAA,CAAA;AAGF,IAAA,OAAO,MAAM,OAAQ,CAAA,GAAA;AAAA,MACnB,cAAA,CAAe,IAAI,CAAM,EAAA,KAAA;AACvB,QAAA,MAAM,wBACJ,GAAA,IAAA,CAAK,iBAAkB,CAAA,EAAA,CAAG,YAAY,CAAA,CAAA;AACxC,QAAA,OAAO,wBAAyB,CAAA,8BAAA;AAAA,UAC9B,EAAA;AAAA,UACA,IAAA;AAAA,SACF,CAAA;AAAA,OACD,CAAA;AAAA,KACH,CAAA;AAAA,GACF;AAAA,EAEA,0BACE,cACyB,EAAA;AACzB,IAAO,OAAA;AAAA,MACL,OAAO,cAAe,CAAA,MAAA;AAAA,QACpB,CAAA,IAAA,KACG,KAAK,MAAW,KAAA,KAAA,CAAA,IAAa,KAAK,MAAO,CAAA,MAAA,IAAU,CACnD,IAAA,IAAA,CAAK,SAAc,KAAA,KAAA,CAAA,IAClB,KAAK,SAAU,CAAA,MAAA,IAAU,KACzB,IAAK,CAAA,SAAA,CAAU,KAAK,CAAM,EAAA,KAAA,EAAA,CAAG,SAAU,CAAA,MAAA,IAAU,CAAC,CAAA;AAAA,OACxD;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEA,gBACE,CAAA,cAAA,EACA,CAAC,MAAA,EAAQ,OAAO,CACA,EAAA;AAChB,IAAA,MAAM,OAA0B,GAAA;AAAA,MAC9B,OAAS,EAAA;AAAA,QACP,MAAM,cAAe,CAAA,IAAA;AAAA,OACvB;AAAA,MACA,UAAA,EAAY,uBAAuB,OAAO,CAAA;AAAA,MAC1C,WAAW,MAAO,CAAA,SAAA;AAAA,MAClB,QAAQ,MAAO,CAAA,MAAA;AAAA,KACjB,CAAA;AACA,IAAA,IAAI,eAAe,YAAc,EAAA;AAC/B,MAAQ,OAAA,CAAA,OAAA,CAAQ,eAAe,cAAe,CAAA,YAAA,CAAA;AAAA,KAChD;AACA,IAAA,IAAI,eAAe,YAAc,EAAA;AAC/B,MAAQ,OAAA,CAAA,OAAA,CAAQ,eAAe,cAAe,CAAA,YAAA,CAAA;AAAA,KAChD;AACA,IAAA,IAAI,eAAe,mBAAqB,EAAA;AACtC,MAAQ,OAAA,CAAA,OAAA,CAAQ,sBAAsB,cAAe,CAAA,mBAAA,CAAA;AAAA,KACvD;AACA,IAAO,OAAA,OAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAM,iBACJ,CAAA,cAAA,EACA,MAC8B,EAAA;AAC9B,IAAA,IAAI,eAAe,iBAAmB,EAAA;AACpC,MAAO,OAAA,CAAC,MAAQ,EAAA,EAAE,CAAA,CAAA;AAAA,KACpB;AACA,IAAA,MAAM,aAA0B,IAAI,GAAA;AAAA,MAClC,MAAA,CAAO,SACJ,CAAA,MAAA,CAAO,kBAAkB,CAAA,CACzB,OAAQ,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,SAAS,CACxB,CAAA,GAAA,CAAI,CAAE,CAAA,KAAA;AA9Wf,QAAA,IAAA,EAAA,CAAA;AA8WkB,QAAA,OAAA,CAAA,EAAA,GAAA,CAAA,CAAE,aAAF,IAAY,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,SAAA,CAAA;AAAA,OAAS,CAAA,CAC9B,OAAO,QAAQ,CAAA;AAAA,KACpB,CAAA;AAEA,IAAI,IAAA,UAAA,CAAW,SAAS,CAAG,EAAA;AACzB,MAAO,OAAA,CAAC,MAAQ,EAAA,EAAE,CAAA,CAAA;AAAA,KACpB;AAEA,IAAM,MAAA,UAAA,GAAa,MAAM,IAAA,CAAK,OAAQ,CAAA,2BAAA;AAAA,MACpC,cAAA;AAAA,MACA,UAAA;AAAA,KACF,CAAA;AAEA,IAAA,MAAA,CAAO,MAAO,CAAA,IAAA,CAAK,GAAG,UAAA,CAAW,MAAM,CAAA,CAAA;AACvC,IAAO,OAAA,CAAC,MAAQ,EAAA,UAAA,CAAW,SAAqC,CAAA,CAAA;AAAA,GAClE;AAAA,EAEQ,kBAAkB,QAA4C,EAAA;AACpE,IAAI,IAAA,IAAA,CAAK,eAAgB,CAAA,QAAQ,CAAG,EAAA;AAClC,MAAO,OAAA,IAAA,CAAK,gBAAgB,QAAQ,CAAA,CAAA;AAAA,KACtC;AAEA,IAAK,IAAA,CAAA,eAAA,CAAgB,QAAQ,CAAA,GAC3B,iCAAkC,CAAA,mCAAA;AAAA,MAChC,QAAA;AAAA,MACA;AAAA,QACE,QAAQ,IAAK,CAAA,MAAA;AAAA,OACf;AAAA,KACF,CAAA;AACF,IAAO,OAAA,IAAA,CAAK,gBAAgB,QAAQ,CAAA,CAAA;AAAA,GACtC;AACF;;AC3VA,MAAM,OAAU,GAAA,CAAC,EACf,KAAA,EAAA,CAAG,eAAe,WAAW,CAAA,CAAA;AAE/B,SAAS,8BACP,OACsB,EAAA;AAvDxB,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAwDE,EAAA,MAAM,OAAqC,GAAAK,0BAAA,CAAO,OAAQ,CAAA,OAAA,EAAS,CAAS,KAAA,KAAA;AAC1E,IAAO,OAAA,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAW,GAAA,WAAA,CAAA;AAAA,GACpC,CAAA,CAAA;AAED,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,CAAA,EAAA,GAAA,OAAA,CAAQ,MAAR,KAAA,IAAA,GAAA,EAAA,GAAkB,EAAC;AAAA,IAC3B,SAAW,EAAA,CAAA,EAAA,GAAA,OAAA,CAAQ,SAAR,KAAA,IAAA,GAAA,EAAA,GAAqB,EAAC;AAAA,GACnC,CAAA;AACF,CAAA;AAEA,MAAM,qBAAA,GAAwB,CAAC,UAA6C,KAAA;AAC1E,EAAA,QAAQ,UAAY;AAAA,IAClB,KAAK,GAAA;AACH,MAAO,OAAA,aAAA,CAAA;AAAA,IACT,KAAK,GAAA;AACH,MAAO,OAAA,oBAAA,CAAA;AAAA,IACT,KAAK,GAAA;AACH,MAAO,OAAA,WAAA,CAAA;AAAA,IACT,KAAK,GAAA;AACH,MAAO,OAAA,cAAA,CAAA;AAAA,IACT;AACE,MAAO,OAAA,eAAA,CAAA;AAAA,GACX;AACF,CAAA,CAAA;AAEO,MAAM,4BAA0D,CAAA;AAAA,EAGrE,WAAA,CAAY,EAAE,MAAA,EAA+C,EAAA;AAC3D,IAAA,IAAA,CAAK,MAAS,GAAA,MAAA,CAAA;AAAA,GAChB;AAAA,EAEA,uBACE,MAC+B,EAAA;AAC/B,IAAM,MAAA,YAAA,GAAe,MAAM,IAAK,CAAA,MAAA,CAAO,kBAAkB,CACtD,CAAA,MAAA,CAAO,MAAO,CAAA,eAAe,CAC7B,CAAA,GAAA;AAAA,MAAI,CAAC,EAAE,UAAA,EAAY,OAAO,UAAY,EAAA,MAAA,OACrC,IAAK,CAAA,aAAA;AAAA,QACH,MAAO,CAAA,cAAA;AAAA,QACP,KAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAO,CAAA,SAAA;AAAA,QACP,MAAA,CAAO,aACL,IAAA,CAAA,2BAAA,EAA8B,MAAO,CAAA,SAAA,CAAA,CAAA;AAAA,OACvC,CAAA,IAAA;AAAA,QACA,CAAC,CACC,KAAA,CAAA,CAAE,EACE,GAAA,CAAA,CAAE,MAAO,CAAA,IAAA;AAAA,UACP,CAAC,EAAE,KAAA,EAA4B,MAAA;AAAA,YAC7B,IAAM,EAAA,UAAA;AAAA,YACN,SAAW,EAAA,KAAA;AAAA,WACb,CAAA;AAAA,YAEF,IAAK,CAAA,0BAAA,CAA2B,MAAO,CAAA,cAAA,CAAe,MAAM,CAAC,CAAA;AAAA,OACrE;AAAA,KACF,CAAA;AAEF,IAAA,OAAO,OAAQ,CAAA,GAAA,CAAI,YAAY,CAAA,CAAE,KAAK,6BAA6B,CAAA,CAAA;AAAA,GACrE;AAAA,EAEA,2BAAA,CACE,gBACA,UAC+B,EAAA;AAC/B,IAAA,MAAM,eAAe,KAAM,CAAA,IAAA,CAAK,UAAU,CAAE,CAAA,GAAA,CAAI,OAAM,EAAM,KAAA;AAC1D,MAAA,MAAM,CAAC,UAAY,EAAA,OAAO,CAAI,GAAA,MAAM,QAAQ,GAAI,CAAA;AAAA,QAC9C,IAAK,CAAA,aAAA;AAAA,UACH,cAAA;AAAA,UACA,gBAAA;AAAA,UACA,SAAA;AAAA,UACA,MAAA;AAAA,UACA,EAAA;AAAA,SACF;AAAA,QACA,KAAK,aAAc,CAAA,cAAA,EAAgB,EAAI,EAAA,IAAA,EAAM,QAAQ,EAAE,CAAA;AAAA,OACxD,CAAA,CAAA;AACD,MAAI,IAAA,UAAA,CAAW,EAAM,IAAA,OAAA,CAAQ,EAAI,EAAA;AAC/B,QAAO,OAAAC,kBAAA;AAAA,UACL;AAAA,YACE,uBAAA,EAAyB,MACvB,OAAA,CAAQ,IAAK,EAAA,CAAE,KAAK,CAAM,CAAA,MAAA,EAAE,IAAM,EAAA,CAAA,EAAI,CAAA,CAAA;AAAA,WAC1C;AAAA,UACA;AAAA,YACE,aAAA,EAAe,MAAM,UAAA,CAAW,IAAK,EAAA;AAAA,WACvC;AAAA,SACA,CAAA,IAAA;AAAA,UACA,CAAC,SAAuC,MAAA;AAAA,YACtC,IAAM,EAAA,WAAA;AAAA,YACN,SAAA;AAAA,WACF,CAAA;AAAA,SACF,CAAA;AAAA,OACF,MAAA,IAAW,WAAW,EAAI,EAAA;AACxB,QAAA,OAAO,IAAK,CAAA,0BAAA,CAA2B,cAAe,CAAA,IAAA,EAAM,OAAO,CAAA,CAAA;AAAA,OACrE;AACA,MAAA,OAAO,IAAK,CAAA,0BAAA,CAA2B,cAAe,CAAA,IAAA,EAAM,UAAU,CAAA,CAAA;AAAA,KACvE,CAAA,CAAA;AAED,IAAA,OAAO,OAAQ,CAAA,GAAA,CAAI,YAAY,CAAA,CAAE,KAAK,6BAA6B,CAAA,CAAA;AAAA,GACrE;AAAA,EAEA,MAAc,0BACZ,CAAA,WAAA,EACA,GAC+B,EAAA;AAC/B,IAAA,MAAM,YAAe,GAAA,IAAI,GAAI,CAAA,GAAA,CAAI,GAAG,CAAE,CAAA,QAAA,CAAA;AACtC,IAAA,IAAA,CAAK,MAAO,CAAA,IAAA;AAAA,MACV,YACE,GAAI,CAAA,MAAA,CAAA,uBAAA,EACoB,+BAA+B,WAAuB,CAAA,SAAA,EAAA,MAAM,IAAI,IAAK,EAAA,CAAA,CAAA,CAAA;AAAA,KACjG,CAAA;AACA,IAAO,OAAA;AAAA,MACL,SAAA,EAAW,qBAAsB,CAAA,GAAA,CAAI,MAAM,CAAA;AAAA,MAC3C,YAAY,GAAI,CAAA,MAAA;AAAA,MAChB,YAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEQ,cACN,cACA,EAAA,KAAA,EACA,UACA,EAAA,MAAA,EACA,WACA,aACmB,EAAA;AACnB,IAAA,MAAM,MAAS,GAAA,CAAC,CAAc,KAAA,kBAAA,CAAmB,CAAC,CAAA,CAAA;AAClD,IAAI,IAAA,YAAA,GAAe,KACf,GAAA,CAAA,MAAA,EAAS,MAAO,CAAA,KAAK,CAAK,CAAA,CAAA,EAAA,MAAA,CAAO,UAAU,CAAA,CAAA,CAAA,GAC3C,CAAQ,KAAA,EAAA,MAAA,CAAO,UAAU,CAAA,CAAA,CAAA,CAAA;AAC7B,IAAA,IAAI,SAAW,EAAA;AACb,MAAgB,YAAA,IAAA,CAAA,YAAA,EAAe,OAAO,SAAS,CAAA,CAAA,CAAA,CAAA;AAAA,KACjD;AACA,IAAgB,YAAA,IAAA,CAAA,CAAA,EAAI,OAAO,MAAM,CAAA,CAAA,CAAA,CAAA;AAEjC,IAAI,IAAA,GAAA,CAAA;AACJ,IAAI,IAAA,WAAA,CAAA;AACJ,IAAA,IAAI,eAAe,mBAAqB,EAAA;AACtC,MAAA,CAAC,GAAK,EAAA,WAAW,CAAI,GAAA,IAAA,CAAK,4BAA4B,cAAc,CAAA,CAAA;AAAA,KAC3D,MAAA,IAAAC,sBAAA,CAAG,cAAe,CAAAC,iBAAA,CAAO,yBAAyB,CAAG,EAAA;AAC9D,MAAA,CAAC,GAAK,EAAA,WAAW,CAAI,GAAA,IAAA,CAAK,kBAAmB,EAAA,CAAA;AAAA,KACxC,MAAA;AACL,MAAA,OAAO,OAAQ,CAAA,MAAA;AAAA,QACb,IAAI,KAAA;AAAA,UACF,gCAAgC,cAAe,CAAA,IAAA,CAAA,+BAAA,CAAA;AAAA,SACjD;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAI,IAAA,GAAA,CAAI,aAAa,GAAK,EAAA;AACxB,MAAA,GAAA,CAAI,QAAW,GAAA,YAAA,CAAA;AAAA,KACV,MAAA;AACL,MAAA,GAAA,CAAI,QAAY,IAAA,YAAA,CAAA;AAAA,KAClB;AAEA,IAAA,IAAI,aAAe,EAAA;AACjB,MAAA,GAAA,CAAI,SAAS,CAAiB,cAAA,EAAA,aAAA,CAAA,CAAA,CAAA;AAAA,KAChC;AAEA,IAAO,OAAAC,yBAAA,CAAM,KAAK,WAAW,CAAA,CAAA;AAAA,GAC/B;AAAA,EAEQ,4BACN,cACoB,EAAA;AA5NxB,IAAA,IAAA,EAAA,CAAA;AA6NI,IAAA,MAAM,WAA2B,GAAA;AAAA,MAC/B,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,MAAQ,EAAA,kBAAA;AAAA,QACR,cAAgB,EAAA,kBAAA;AAAA,QAChB,aAAA,EAAe,UAAU,cAAe,CAAA,mBAAA,CAAA,CAAA;AAAA,OAC1C;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,GAAW,GAAA,IAAI,GAAI,CAAA,cAAA,CAAe,GAAG,CAAA,CAAA;AAC3C,IAAI,IAAA,GAAA,CAAI,aAAa,QAAU,EAAA;AAC7B,MAAY,WAAA,CAAA,KAAA,GAAQ,IAAIC,gBAAA,CAAM,KAAM,CAAA;AAAA,QAClC,EACE,EAAA,CAAA,EAAA,GAAAC,iCAAA;AAAA,UACE,cAAe,CAAA,MAAA;AAAA,UACf,cAAe,CAAA,MAAA;AAAA,cAFjB,IAGK,GAAA,EAAA,GAAA,KAAA,CAAA;AAAA,QACP,kBAAA,EAAoB,CAAC,cAAe,CAAA,aAAA;AAAA,OACrC,CAAA,CAAA;AAAA,KACH;AACA,IAAO,OAAA,CAAC,KAAK,WAAW,CAAA,CAAA;AAAA,GAC1B;AAAA,EACQ,kBAAyC,GAAA;AAC/C,IAAM,MAAA,EAAA,GAAK,IAAIC,qBAAW,EAAA,CAAA;AAC1B,IAAA,EAAA,CAAG,eAAgB,EAAA,CAAA;AAEnB,IAAM,MAAA,OAAA,GAAU,GAAG,iBAAkB,EAAA,CAAA;AACrC,IAAM,MAAA,IAAA,GAAO,GAAG,cAAe,EAAA,CAAA;AAE/B,IAAA,MAAM,QAAQL,sBAAG,CAAA,YAAA,CAAa,IAAK,CAAA,YAAA,CAAa,OAAO,SAAS,CAAA,CAAA;AAEhE,IAAA,MAAM,WAA2B,GAAA;AAAA,MAC/B,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,MAAQ,EAAA,kBAAA;AAAA,QACR,cAAgB,EAAA,kBAAA;AAAA,QAChB,eAAe,CAAU,OAAA,EAAA,KAAA,CAAA,CAAA;AAAA,OAC3B;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,GAAM,GAAA,IAAI,GAAI,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAClC,IAAI,IAAA,GAAA,CAAI,aAAa,QAAU,EAAA;AAC7B,MAAY,WAAA,CAAA,KAAA,GAAQ,IAAIG,gBAAA,CAAM,KAAM,CAAA;AAAA,QAClC,EAAI,EAAAH,sBAAA,CAAG,YAAa,CAAA,OAAA,CAAQ,MAAgB,CAAA;AAAA,OAC7C,CAAA,CAAA;AAAA,KACH;AACA,IAAO,OAAA,CAAC,KAAK,WAAW,CAAA,CAAA;AAAA,GAC1B;AACF;;ACzOO,MAAM,yBAAoC,GAAA,uBAAA;AAO1C,MAAM,eAAgB,CAAA;AAAA,EAG3B,WAAA,CACmB,QACA,eACjB,EAAA;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA,CAAA;AAJnB,IAAiB,IAAA,CAAA,wBAAA,uBAA+B,GAA4B,EAAA,CAAA;AAAA,GAKzE;AAAA,EAEI,oBAAuC,GAAA;AAC5C,IAAO,OAAA,OAAO,GAAK,EAAA,GAAA,EAAK,IAAS,KAAA;AAC/B,MAAA,MAAM,UAAa,GAAA,MAAM,IAAK,CAAA,aAAA,CAAc,GAAG,CAAA,CAAA;AAC/C,MAAW,UAAA,CAAA,GAAA,EAAK,KAAK,IAAI,CAAA,CAAA;AAAA,KAC3B,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAc,WAA+C,EAAA;AACzE,IAAA,MAAM,eAAkB,GAAA,MAAM,IAAK,CAAA,oBAAA,CAAqB,WAAW,CAAA,CAAA;AACnE,IAAA,IAAI,UAAa,GAAA,IAAA,CAAK,wBAAyB,CAAA,GAAA,CAAI,gBAAgB,IAAI,CAAA,CAAA;AACvE,IAAA,IAAI,CAAC,UAAY,EAAA;AAQf,MAAM,MAAA,MAAA,GAAS,KAAK,MAAO,CAAA,KAAA,CAAM,EAAE,OAAS,EAAA,eAAA,CAAgB,MAAM,CAAA,CAAA;AAClE,MAAA,UAAA,GAAaM,yCAAsB,CAAA;AAAA,QACjC,aAAa,MAAM,MAAA;AAAA,QACnB,MAAA,EAAQ,CAAC,eAAgB,CAAA,aAAA;AAAA,QACzB,MAAA,EAAQ,OAAM,GAAO,KAAA;AA5E7B,UAAA,IAAA,EAAA,CAAA;AA8EU,UAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,oBAAA,CAAqB,GAAG,CAAA,CAAA;AACnD,UAAA,MAAM,GAAM,GAAA,IAAI,GAAI,CAAA,OAAA,CAAQ,GAAG,CAAA,CAAA;AAC/B,UAAO,OAAA;AAAA,YACL,UAAU,GAAI,CAAA,QAAA;AAAA,YACd,MAAM,GAAI,CAAA,QAAA;AAAA,YACV,MAAM,GAAI,CAAA,IAAA;AAAA,YACV,KAAI,EAAuB,GAAAF,iCAAA,CAAA,EAAA,EAAI,OAAQ,CAAA,MAAM,MAAzC,IAA4C,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,QAAA,EAAA;AAAA,WAClD,CAAA;AAAA,SACF;AAAA,QACA,aAAa,EAAE,CAAC,IAAI,WAAY,CAAA,OAAA,CAAA,CAAS,GAAG,EAAG,EAAA;AAAA,QAC/C,OAAS,EAAA,CAAC,KAAO,EAAA,GAAA,EAAK,GAAQ,KAAA;AAC5B,UAAA,MAAM,eAAe,IAAIrB,qBAAA;AAAA,YACvB,YAAY,eAAgB,CAAA,IAAA,CAAA,eAAA,CAAA;AAAA,YAC5B,KAAA;AAAA,WACF,CAAA;AAEA,UAAA,MAAA,CAAO,MAAM,YAAY,CAAA,CAAA;AAEzB,UAAA,MAAM,IAA0B,GAAA;AAAA,YAC9B,KAAA,EAAOwB,sBAAe,YAAc,EAAA;AAAA,cAClC,YAAA,EAAc,OAAQ,CAAA,GAAA,CAAI,QAAa,KAAA,aAAA;AAAA,aACxC,CAAA;AAAA,YACD,SAAS,EAAE,MAAA,EAAQ,IAAI,MAAQ,EAAA,GAAA,EAAK,IAAI,WAAY,EAAA;AAAA,YACpD,QAAA,EAAU,EAAE,UAAA,EAAY,GAAI,EAAA;AAAA,WAC9B,CAAA;AAEA,UAAA,GAAA,CAAI,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,SAC3B;AAAA,OACD,CAAA,CAAA;AAED,MAAA,IAAA,CAAK,wBAAyB,CAAA,GAAA,CAAI,eAAgB,CAAA,IAAA,EAAM,UAAU,CAAA,CAAA;AAAA,KACpE;AAEA,IAAO,OAAA,UAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAc,qBAAqB,GAAuC,EAAA;AACxE,IAAM,MAAA,WAAA,GAAc,GAAI,CAAA,MAAA,CAAO,yBAAyB,CAAA,CAAA;AACxD,IAAA,IAAI,CAAC,WAAa,EAAA;AAChB,MAAM,MAAA,IAAId,iBAAW,CAAA,CAAA,SAAA,EAAY,yBAAoC,CAAA,SAAA,CAAA,CAAA,CAAA;AAAA,KACvE;AAEA,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,eAAA,CACxB,aACA,CAAA,IAAA,CAAK,CAAY,QAAA,KAAA,QAAA,CAAS,IAAK,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,IAAA,KAAS,WAAW,CAAC,CAAA,CAAA;AAC9D,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAM,MAAA,IAAIe,oBAAc,CAAA,CAAA,SAAA,EAAY,WAAwB,CAAA,WAAA,CAAA,CAAA,CAAA;AAAA,KAC9D;AAEA,IAAO,OAAA,OAAA,CAAA;AAAA,GACT;AACF;;ACzDO,MAAM,iBAAkB,CAAA;AAAA,EAc7B,YAA+B,GAA4B,EAAA;AAA5B,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA,CAAA;AAZ/B,IAAQ,IAAA,CAAA,6BAAA,GAA0CC,eAAS,UAAW,CAAA;AAAA,MACpE,OAAS,EAAA,EAAA;AAAA,KACV,CAAA,CAAA;AAAA,GAU2D;AAAA,EAJ5D,OAAO,cAAc,GAA4B,EAAA;AAC/C,IAAO,OAAA,IAAI,kBAAkB,GAAG,CAAA,CAAA;AAAA,GAClC;AAAA,EAIA,MAAa,KAAiC,GAAA;AAC5C,IAAM,MAAA,MAAA,GAAS,KAAK,GAAI,CAAA,MAAA,CAAA;AACxB,IAAM,MAAA,MAAA,GAAS,KAAK,GAAI,CAAA,MAAA,CAAA;AAExB,IAAA,MAAA,CAAO,KAAK,iCAAiC,CAAA,CAAA;AAE7C,IAAA,IAAI,CAAC,MAAA,CAAO,GAAI,CAAA,YAAY,CAAG,EAAA;AAC7B,MAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,aAAe,EAAA;AAC1C,QAAM,MAAA,IAAI,MAAM,qCAAqC,CAAA,CAAA;AAAA,OACvD;AACA,MAAO,MAAA,CAAA,IAAA;AAAA,QACL,uEAAA;AAAA,OACF,CAAA;AACA,MAAO,OAAA;AAAA,QACL,QAAQC,0BAAO,EAAA;AAAA,OACjB,CAAA;AAAA,KACF;AACA,IAAM,MAAA,eAAA,GAAkB,KAAK,oBAAqB,EAAA,CAAA;AAElD,IAAM,MAAA,OAAA,GAAU,KAAK,UAAW,EAAA,CAAA;AAEhC,IAAM,MAAA,eAAA,GAAkB,KAAK,kBAAmB,EAAA,CAAA;AAEhD,IAAA,MAAM,KAAQ,GAAA,IAAA,CAAK,QAAS,CAAA,MAAA,EAAQ,eAAe,CAAA,CAAA;AAEnD,IAAM,MAAA,cAAA,GAAiB,KAAK,iBAAkB,EAAA,CAAA;AAE9C,IAAM,MAAA,eAAA,GAAkB,KAAK,kBAAmB,CAAA;AAAA,MAC9C,MAAA;AAAA,MACA,OAAA;AAAA,MACA,cAAA;AAAA,MACA,eAAA;AAAA,MACA,kBAAA,EAAoB,KAAK,qBAAsB,EAAA;AAAA,KAChD,CAAA,CAAA;AAED,IAAA,MAAM,SAAS,IAAK,CAAA,WAAA;AAAA,MAClB,eAAA;AAAA,MACA,eAAA;AAAA,MACA,KAAK,GAAI,CAAA,UAAA;AAAA,MACT,KAAA;AAAA,KACF,CAAA;AAEA,IAAO,OAAA;AAAA,MACL,eAAA;AAAA,MACA,eAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA;AAAA,MACA,eAAA;AAAA,MACA,MAAA;AAAA,MACA,cAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEO,mBAAmB,eAA8C,EAAA;AACtE,IAAA,IAAA,CAAK,eAAkB,GAAA,eAAA,CAAA;AACvB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,iCAAiC,eAA2B,EAAA;AACjE,IAAA,IAAA,CAAK,6BAAgC,GAAA,eAAA,CAAA;AACrC,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,mBAAmB,eAA6C,EAAA;AACrE,IAAA,IAAA,CAAK,eAAkB,GAAA,eAAA,CAAA;AACvB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,WAAW,OAA6B,EAAA;AAC7C,IAAA,IAAA,CAAK,OAAU,GAAA,OAAA,CAAA;AACf,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,kBAAkB,cAA2C,EAAA;AAClE,IAAA,IAAA,CAAK,cAAiB,GAAA,cAAA,CAAA;AACtB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,SAAS,KAAyB,EAAA;AACvC,IAAA,IAAA,CAAK,KAAQ,GAAA,KAAA,CAAA;AACb,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEU,oBAAuB,GAAA;AA3KnC,IAAA,IAAA,EAAA,CAAA;AA4KI,IAAM,MAAA,eAAA,GAAA,CAAA,CACJ,UAAK,GAAI,CAAA,MAAA,CAAO,uBAAuB,4BAA4B,CAAA,KAAnE,IAAwE,GAAA,EAAA,GAAA,EACxE,EAAA,GAAA;AAAA,MACA,CACG,CAAA,MAAA;AAAA,QACC,KAAA,EAAO,CAAE,CAAA,SAAA,CAAU,OAAO,CAAA;AAAA,QAC1B,UAAA,EAAY,CAAE,CAAA,SAAA,CAAU,YAAY,CAAA;AAAA,QACpC,MAAA,EAAQ,CAAE,CAAA,SAAA,CAAU,QAAQ,CAAA;AAAA,QAC5B,UAAY,EAAA,iBAAA;AAAA,OACd,CAAA;AAAA,KACJ,CAAA;AAEA,IAAA,IAAA,CAAK,IAAI,MAAO,CAAA,IAAA;AAAA,MACd,sDAAsD,eAAgB,CAAA,MAAA,CAAA,CAAA;AAAA,KACxE,CAAA;AACA,IAAO,OAAA,eAAA,CAAA;AAAA,GACT;AAAA,EAEU,qBACR,eAC4B,EAAA;AAC5B,IAAM,MAAA,MAAA,GAAS,KAAK,GAAI,CAAA,MAAA,CAAA;AACxB,IAAA,IAAA,CAAK,eAAkB,GAAA,0BAAA;AAAA,MACrB,MAAA;AAAA,MACA,KAAK,GAAI,CAAA,UAAA;AAAA,MACT,eAAA;AAAA,KACF,CAAA;AAEA,IAAA,OAAO,IAAK,CAAA,eAAA,CAAA;AAAA,GACd;AAAA,EAEU,qBACR,OAC2B,EAAA;AAC3B,IAAK,IAAA,CAAA,eAAA,GAAkB,IAAI,uBAAA,CAAwB,OAAO,CAAA,CAAA;AAC1D,IAAA,OAAO,IAAK,CAAA,eAAA,CAAA;AAAA,GACd;AAAA,EAEU,YAAkC,GAAA;AAC1C,IAAK,IAAA,CAAA,OAAA,GAAU,IAAI,4BAA6B,CAAA;AAAA,MAC9C,MAAA,EAAQ,KAAK,GAAI,CAAA,MAAA;AAAA,KAClB,CAAA,CAAA;AAED,IAAA,OAAO,IAAK,CAAA,OAAA,CAAA;AAAA,GACd;AAAA,EAEU,mBAAA,CACR,QACA,eAC0B,EAAA;AAC1B,IAAA,QAAQ,MAAQ;AAAA,MACd,KAAK,aAAA;AACH,QAAK,IAAA,CAAA,cAAA,GACH,IAAK,CAAA,8BAAA,CAA+B,eAAe,CAAA,CAAA;AACrD,QAAA,MAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAK,IAAA,CAAA,cAAA,GAAiB,IAAK,CAAA,uBAAA,CAAwB,eAAe,CAAA,CAAA;AAClE,QAAA,MAAA;AAAA,MACF;AACE,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAgD,6CAAA,EAAA,MAAA,CAAA,CAAA,CAAA;AAAA,SAClD,CAAA;AAAA,KACJ;AAEA,IAAA,OAAO,IAAK,CAAA,cAAA,CAAA;AAAA,GACd;AAAA,EAEU,+BACR,eAC0B,EAAA;AAC1B,IAAO,OAAA,IAAI,0BAA0B,eAAe,CAAA,CAAA;AAAA,GACtD;AAAA,EAEU,wBACR,gBAC0B,EAAA;AAC1B,IAAM,MAAA,IAAI,MAAM,iBAAiB,CAAA,CAAA;AAAA,GACnC;AAAA,EAEU,UAAA,CACR,QACA,eACiB,EAAA;AACjB,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAI,eAAgB,CAAA,MAAA,EAAQ,eAAe,CAAA,CAAA;AACxD,IAAA,OAAO,IAAK,CAAA,KAAA,CAAA;AAAA,GACd;AAAA,EAEU,WACR,CAAA,eAAA,EACA,eACA,EAAA,UAAA,EACA,KACgB,EAAA;AAChB,IAAM,MAAA,MAAA,GAAS,KAAK,GAAI,CAAA,MAAA,CAAA;AACxB,IAAA,MAAM,SAASA,0BAAO,EAAA,CAAA;AACtB,IAAA,MAAA,CAAO,GAAI,CAAA,QAAA,EAAU,KAAM,CAAA,oBAAA,EAAsB,CAAA,CAAA;AACjD,IAAO,MAAA,CAAA,GAAA,CAAIC,2BAAQ,CAAA,IAAA,EAAM,CAAA,CAAA;AAGzB,IAAA,MAAA,CAAO,IAAK,CAAA,sBAAA,EAAwB,OAAO,GAAA,EAAK,GAAQ,KAAA;AACtD,MAAM,MAAA,SAAA,GAAY,IAAI,MAAO,CAAA,SAAA,CAAA;AAC7B,MAAA,MAAM,cAAsC,GAAI,CAAA,IAAA,CAAA;AAChD,MAAI,IAAA;AACF,QAAM,MAAA,QAAA,GAAW,MAAM,eAAA,CAAgB,4BAA6B,CAAA;AAAA,UAClE,QAAQ,WAAY,CAAA,MAAA;AAAA,UACpB,IAAA,EAAM,WAAY,CAAA,IAAA,IAAQ,EAAC;AAAA,SAC5B,CAAA,CAAA;AACD,QAAA,GAAA,CAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,eACV,CAAP,EAAA;AACA,QAAO,MAAA,CAAA,KAAA;AAAA,UACL,6CAA6C,SAAoB,CAAA,QAAA,EAAA,CAAA,CAAA,CAAA;AAAA,SACnE,CAAA;AACA,QAAI,GAAA,CAAA,MAAA,CAAO,GAAG,CAAE,CAAA,IAAA,CAAK,EAAE,KAAO,EAAA,CAAA,CAAE,SAAS,CAAA,CAAA;AAAA,OAC3C;AAAA,KACD,CAAA,CAAA;AAED,IAAA,MAAA,CAAO,GAAI,CAAA,WAAA,EAAa,OAAO,CAAA,EAAG,GAAQ,KAAA;AACxC,MAAA,MAAM,cAAiB,GAAA,MAAM,IAAK,CAAA,mBAAA,CAAoB,eAAe,CAAA,CAAA;AACrE,MAAA,GAAA,CAAI,IAAK,CAAA;AAAA,QACP,KAAA,EAAO,cAAe,CAAA,GAAA,CAAI,CAAO,EAAA,MAAA;AAAA,UAC/B,MAAM,EAAG,CAAA,IAAA;AAAA,UACT,cAAc,EAAG,CAAA,YAAA;AAAA,UACjB,cAAc,EAAG,CAAA,YAAA;AAAA,UACjB,mBAAmB,EAAG,CAAA,iBAAA;AAAA,SACtB,CAAA,CAAA;AAAA,OACH,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAED,IAA0B,yBAAA,CAAA,MAAA,EAAQ,YAAY,eAAe,CAAA,CAAA;AAE7D,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAgB,oBACd,eACA,EAAA;AACA,IAAM,MAAA,cAAA,GAAiB,MAAM,eAAA,CAAgB,WAAY,EAAA,CAAA;AAEzD,IAAA,IAAA,CAAK,IAAI,MAAO,CAAA,IAAA;AAAA,MACd,iDAAiD,cAAe,CAAA,MAAA,CAAA,CAAA;AAAA,KAClE,CAAA;AAEA,IAAO,OAAA,cAAA,CAAA;AAAA,GACT;AAAA,EAEU,uBAA0B,GAAA;AAClC,IAAO,OAAA,IAAA,CAAK,IAAI,MAAO,CAAA,SAAA;AAAA,MACrB,sCAAA;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEU,UAAgC,GAAA;AAnU5C,IAAA,IAAA,EAAA,CAAA;AAoUI,IAAA,OAAA,CAAO,EAAK,GAAA,IAAA,CAAA,OAAA,KAAL,IAAgB,GAAA,EAAA,GAAA,IAAA,CAAK,YAAa,EAAA,CAAA;AAAA,GAC3C;AAAA,EAEU,kBAAqB,GAAA;AAvUjC,IAAA,IAAA,EAAA,CAAA;AAwUI,IAAA,OAAA,CACE,UAAK,eAAL,KAAA,IAAA,GAAA,EAAA,GACA,IAAK,CAAA,oBAAA,CAAqB,KAAK,6BAA6B,CAAA,CAAA;AAAA,GAEhE;AAAA,EAEU,iBAA8C,GAAA;AA9U1D,IAAA,IAAA,EAAA,CAAA;AA+UI,IACE,OAAA,CAAA,EAAA,GAAA,IAAA,CAAK,cAAL,KAAA,IAAA,GAAA,EAAA,GACA,IAAK,CAAA,mBAAA;AAAA,MACH,KAAK,uBAAwB,EAAA;AAAA,MAC7B,KAAK,kBAAmB,EAAA;AAAA,KAC1B,CAAA;AAAA,GAEJ;AAAA,EAEU,mBAAmB,OAA2C,EAAA;AAxV1E,IAAA,IAAA,EAAA,CAAA;AAyVI,IAAA,OAAA,CAAO,EAAK,GAAA,IAAA,CAAA,eAAA,KAAL,IAAwB,GAAA,EAAA,GAAA,IAAA,CAAK,qBAAqB,OAAO,CAAA,CAAA;AAAA,GAClE;AAAA,EAEU,qBAAwB,GAAA;AAChC,IAAM,MAAA,yBAAA,GAA4B,IAAK,CAAA,GAAA,CAAI,MAAO,CAAA,sBAAA;AAAA,MAChD,wBAAA;AAAA,KACF,CAAA;AAEA,IAAM,MAAA,mBAAA,GAAsB,IAAK,CAAA,GAAA,CAAI,MAAO,CAAA,iBAAA;AAAA,MAC1C,gCAAA;AAAA,KACF,CAAA;AAEA,IAAI,IAAA,kBAAA,CAAA;AAEJ,IAAA,IAAI,yBAA2B,EAAA;AAC7B,MAAA,kBAAA,GAAqB,eAAgB,CAAA,MAAA;AAAA,QAAO,CAC1C,GAAA,KAAA,yBAAA,CAA0B,QAAS,CAAA,GAAA,CAAI,UAAU,CAAA;AAAA,OACnD,CAAA;AAAA,KACF;AAEA,IAAA,IAAI,mBAAqB,EAAA;AACvB,MAAA,kBAAA,GAAqB,kBAAsB,IAAA,IAAA,GAAA,kBAAA,GAAA,eAAA,CAAA;AAE3C,MAAA,KAAA,MAAW,OAAO,kBAAoB,EAAA;AACpC,QAAA,IAAI,mBAAoB,CAAA,GAAA,CAAI,GAAI,CAAA,UAAU,CAAG,EAAA;AAC3C,UAAA,GAAA,CAAI,UAAa,GAAA,mBAAA,CAAoB,SAAU,CAAA,GAAA,CAAI,UAAU,CAAA,CAAA;AAAA,SAC/D;AAAA,OACF;AAAA,KACF;AAEA,IAAO,OAAA,kBAAA,CAAA;AAAA,GACT;AAAA,EAEU,QAAA,CACR,QACA,eACA,EAAA;AA7XJ,IAAA,IAAA,EAAA,CAAA;AA8XI,IAAA,OAAA,CAAO,UAAK,KAAL,KAAA,IAAA,GAAA,EAAA,GAAc,IAAK,CAAA,UAAA,CAAW,QAAQ,eAAe,CAAA,CAAA;AAAA,GAC9D;AACF;;AC7UA,eAAsB,aACpB,OACyB,EAAA;AACzB,EAAA,MAAM,EAAE,MAAA,EAAW,GAAA,MAAM,iBAAkB,CAAA,aAAA,CAAc,OAAO,CAAA,CAC7D,kBAAmB,CAAA,OAAA,CAAQ,eAAe,CAAA,CAC1C,KAAM,EAAA,CAAA;AACT,EAAO,OAAA,MAAA,CAAA;AACT;;;;;;;;;;;;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
*
|
|
15
|
-
* @
|
|
15
|
+
* @public
|
|
16
16
|
*/
|
|
17
17
|
interface ObjectFetchParams {
|
|
18
18
|
serviceId: string;
|
|
@@ -25,7 +25,7 @@ interface ObjectFetchParams {
|
|
|
25
25
|
/**
|
|
26
26
|
* Fetches information from a kubernetes cluster using the cluster details object to target a specific cluster
|
|
27
27
|
*
|
|
28
|
-
* @
|
|
28
|
+
* @public
|
|
29
29
|
*/
|
|
30
30
|
interface KubernetesFetcher {
|
|
31
31
|
fetchObjectsForService(params: ObjectFetchParams): Promise<FetchResponseWrapper>;
|
|
@@ -33,7 +33,7 @@ interface KubernetesFetcher {
|
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
35
|
*
|
|
36
|
-
* @
|
|
36
|
+
* @public
|
|
37
37
|
*/
|
|
38
38
|
interface FetchResponseWrapper {
|
|
39
39
|
errors: KubernetesFetchError[];
|
|
@@ -41,7 +41,7 @@ interface FetchResponseWrapper {
|
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
*
|
|
44
|
-
* @
|
|
44
|
+
* @public
|
|
45
45
|
*/
|
|
46
46
|
interface ObjectToFetch {
|
|
47
47
|
objectType: KubernetesObjectTypes;
|
|
@@ -51,19 +51,19 @@ interface ObjectToFetch {
|
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
53
|
*
|
|
54
|
-
* @
|
|
54
|
+
* @public
|
|
55
55
|
*/
|
|
56
56
|
interface CustomResource extends ObjectToFetch {
|
|
57
57
|
objectType: 'customresources';
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
60
|
*
|
|
61
|
-
* @
|
|
61
|
+
* @public
|
|
62
62
|
*/
|
|
63
63
|
declare type KubernetesObjectTypes = 'pods' | 'services' | 'configmaps' | 'deployments' | 'limitranges' | 'replicasets' | 'horizontalpodautoscalers' | 'jobs' | 'cronjobs' | 'ingresses' | 'customresources' | 'statefulsets' | 'daemonsets';
|
|
64
64
|
/**
|
|
65
65
|
* Used to load cluster details from different sources
|
|
66
|
-
* @
|
|
66
|
+
* @public
|
|
67
67
|
*/
|
|
68
68
|
interface KubernetesClustersSupplier {
|
|
69
69
|
/**
|
|
@@ -75,7 +75,7 @@ interface KubernetesClustersSupplier {
|
|
|
75
75
|
getClusters(): Promise<ClusterDetails[]>;
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
|
-
* @
|
|
78
|
+
* @public
|
|
79
79
|
*/
|
|
80
80
|
interface ServiceLocatorRequestContext {
|
|
81
81
|
objectTypesToFetch: Set<ObjectToFetch>;
|
|
@@ -83,7 +83,7 @@ interface ServiceLocatorRequestContext {
|
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
85
|
* Used to locate which cluster(s) a service is running on
|
|
86
|
-
* @
|
|
86
|
+
* @public
|
|
87
87
|
*/
|
|
88
88
|
interface KubernetesServiceLocator {
|
|
89
89
|
getClustersByEntity(entity: Entity, requestContext: ServiceLocatorRequestContext): Promise<{
|
|
@@ -92,12 +92,12 @@ interface KubernetesServiceLocator {
|
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
*
|
|
95
|
-
* @
|
|
95
|
+
* @public
|
|
96
96
|
*/
|
|
97
97
|
declare type ServiceLocatorMethod = 'multiTenant' | 'http';
|
|
98
98
|
/**
|
|
99
99
|
*
|
|
100
|
-
* @
|
|
100
|
+
* @public
|
|
101
101
|
*/
|
|
102
102
|
interface ClusterDetails {
|
|
103
103
|
/**
|
|
@@ -159,25 +159,25 @@ interface ClusterDetails {
|
|
|
159
159
|
}
|
|
160
160
|
/**
|
|
161
161
|
*
|
|
162
|
-
* @
|
|
162
|
+
* @public
|
|
163
163
|
*/
|
|
164
164
|
interface GKEClusterDetails extends ClusterDetails {
|
|
165
165
|
}
|
|
166
166
|
/**
|
|
167
167
|
*
|
|
168
|
-
* @
|
|
168
|
+
* @public
|
|
169
169
|
*/
|
|
170
170
|
interface AzureClusterDetails extends ClusterDetails {
|
|
171
171
|
}
|
|
172
172
|
/**
|
|
173
173
|
*
|
|
174
|
-
* @
|
|
174
|
+
* @public
|
|
175
175
|
*/
|
|
176
176
|
interface ServiceAccountClusterDetails extends ClusterDetails {
|
|
177
177
|
}
|
|
178
178
|
/**
|
|
179
179
|
*
|
|
180
|
-
* @
|
|
180
|
+
* @public
|
|
181
181
|
*/
|
|
182
182
|
interface AWSClusterDetails extends ClusterDetails {
|
|
183
183
|
assumeRole?: string;
|
|
@@ -185,7 +185,7 @@ interface AWSClusterDetails extends ClusterDetails {
|
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
187
|
*
|
|
188
|
-
* @
|
|
188
|
+
* @public
|
|
189
189
|
*/
|
|
190
190
|
interface KubernetesObjectsProviderOptions {
|
|
191
191
|
logger: Logger;
|
|
@@ -196,12 +196,12 @@ interface KubernetesObjectsProviderOptions {
|
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
198
198
|
*
|
|
199
|
-
* @
|
|
199
|
+
* @public
|
|
200
200
|
*/
|
|
201
201
|
declare type ObjectsByEntityRequest = KubernetesRequestBody;
|
|
202
202
|
/**
|
|
203
203
|
*
|
|
204
|
-
* @
|
|
204
|
+
* @public
|
|
205
205
|
*/
|
|
206
206
|
interface KubernetesObjectsByEntity {
|
|
207
207
|
entity: Entity;
|
|
@@ -209,14 +209,14 @@ interface KubernetesObjectsByEntity {
|
|
|
209
209
|
}
|
|
210
210
|
/**
|
|
211
211
|
*
|
|
212
|
-
* @
|
|
212
|
+
* @public
|
|
213
213
|
*/
|
|
214
214
|
interface CustomResourcesByEntity extends KubernetesObjectsByEntity {
|
|
215
215
|
customResources: CustomResourceMatcher[];
|
|
216
216
|
}
|
|
217
217
|
/**
|
|
218
218
|
*
|
|
219
|
-
* @
|
|
219
|
+
* @public
|
|
220
220
|
*/
|
|
221
221
|
interface KubernetesObjectsProvider {
|
|
222
222
|
getKubernetesObjectsByEntity(kubernetesObjectsByEntity: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse>;
|
|
@@ -225,7 +225,7 @@ interface KubernetesObjectsProvider {
|
|
|
225
225
|
|
|
226
226
|
/**
|
|
227
227
|
*
|
|
228
|
-
* @
|
|
228
|
+
* @public
|
|
229
229
|
*/
|
|
230
230
|
interface KubernetesAuthTranslator {
|
|
231
231
|
decorateClusterDetailsWithAuth(clusterDetails: ClusterDetails, authConfig: KubernetesRequestAuth): Promise<ClusterDetails>;
|
|
@@ -233,7 +233,7 @@ interface KubernetesAuthTranslator {
|
|
|
233
233
|
|
|
234
234
|
/**
|
|
235
235
|
*
|
|
236
|
-
* @
|
|
236
|
+
* @public
|
|
237
237
|
*/
|
|
238
238
|
declare type SigningCreds = {
|
|
239
239
|
accessKeyId: string | undefined;
|
|
@@ -242,7 +242,7 @@ declare type SigningCreds = {
|
|
|
242
242
|
};
|
|
243
243
|
/**
|
|
244
244
|
*
|
|
245
|
-
* @
|
|
245
|
+
* @public
|
|
246
246
|
*/
|
|
247
247
|
declare class AwsIamKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
248
248
|
validCredentials(creds: SigningCreds): boolean;
|
|
@@ -254,7 +254,7 @@ declare class AwsIamKubernetesAuthTranslator implements KubernetesAuthTranslator
|
|
|
254
254
|
|
|
255
255
|
/**
|
|
256
256
|
*
|
|
257
|
-
* @
|
|
257
|
+
* @public
|
|
258
258
|
*/
|
|
259
259
|
declare class AzureIdentityKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
260
260
|
private readonly logger;
|
|
@@ -271,7 +271,7 @@ declare class AzureIdentityKubernetesAuthTranslator implements KubernetesAuthTra
|
|
|
271
271
|
|
|
272
272
|
/**
|
|
273
273
|
*
|
|
274
|
-
* @
|
|
274
|
+
* @public
|
|
275
275
|
*/
|
|
276
276
|
declare class GoogleKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
277
277
|
decorateClusterDetailsWithAuth(clusterDetails: GKEClusterDetails, authConfig: KubernetesRequestAuth): Promise<GKEClusterDetails>;
|
|
@@ -279,7 +279,7 @@ declare class GoogleKubernetesAuthTranslator implements KubernetesAuthTranslator
|
|
|
279
279
|
|
|
280
280
|
/**
|
|
281
281
|
*
|
|
282
|
-
* @
|
|
282
|
+
* @public
|
|
283
283
|
*/
|
|
284
284
|
declare class GoogleServiceAccountAuthTranslator implements KubernetesAuthTranslator {
|
|
285
285
|
decorateClusterDetailsWithAuth(clusterDetails: GKEClusterDetails): Promise<GKEClusterDetails>;
|
|
@@ -287,7 +287,7 @@ declare class GoogleServiceAccountAuthTranslator implements KubernetesAuthTransl
|
|
|
287
287
|
|
|
288
288
|
/**
|
|
289
289
|
*
|
|
290
|
-
* @
|
|
290
|
+
* @public
|
|
291
291
|
*/
|
|
292
292
|
declare class KubernetesAuthTranslatorGenerator {
|
|
293
293
|
static getKubernetesAuthTranslatorInstance(authProvider: string, options: {
|
|
@@ -297,7 +297,7 @@ declare class KubernetesAuthTranslatorGenerator {
|
|
|
297
297
|
|
|
298
298
|
/**
|
|
299
299
|
*
|
|
300
|
-
* @
|
|
300
|
+
* @public
|
|
301
301
|
*/
|
|
302
302
|
declare class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
303
303
|
decorateClusterDetailsWithAuth(clusterDetails: ServiceAccountClusterDetails): Promise<ServiceAccountClusterDetails>;
|
|
@@ -305,7 +305,7 @@ declare class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
|
305
305
|
|
|
306
306
|
/**
|
|
307
307
|
*
|
|
308
|
-
* @
|
|
308
|
+
* @public
|
|
309
309
|
*/
|
|
310
310
|
declare class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
311
311
|
decorateClusterDetailsWithAuth(clusterDetails: ClusterDetails, authConfig: KubernetesRequestAuth): Promise<ClusterDetails>;
|
|
@@ -314,13 +314,13 @@ declare class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
|
314
314
|
/**
|
|
315
315
|
* The header that is used to specify the cluster name.
|
|
316
316
|
*
|
|
317
|
-
* @
|
|
317
|
+
* @public
|
|
318
318
|
*/
|
|
319
319
|
declare const HEADER_KUBERNETES_CLUSTER: string;
|
|
320
320
|
/**
|
|
321
321
|
* A proxy that routes requests to the Kubernetes API.
|
|
322
322
|
*
|
|
323
|
-
* @
|
|
323
|
+
* @public
|
|
324
324
|
*/
|
|
325
325
|
declare class KubernetesProxy {
|
|
326
326
|
private readonly logger;
|
|
@@ -334,7 +334,7 @@ declare class KubernetesProxy {
|
|
|
334
334
|
|
|
335
335
|
/**
|
|
336
336
|
*
|
|
337
|
-
* @
|
|
337
|
+
* @public
|
|
338
338
|
*/
|
|
339
339
|
interface KubernetesEnvironment {
|
|
340
340
|
logger: Logger;
|
|
@@ -344,7 +344,7 @@ interface KubernetesEnvironment {
|
|
|
344
344
|
/**
|
|
345
345
|
* The return type of the `KubernetesBuilder.build` method
|
|
346
346
|
*
|
|
347
|
-
* @
|
|
347
|
+
* @public
|
|
348
348
|
*/
|
|
349
349
|
declare type KubernetesBuilderReturn = Promise<{
|
|
350
350
|
router: express.Router;
|
|
@@ -357,7 +357,7 @@ declare type KubernetesBuilderReturn = Promise<{
|
|
|
357
357
|
}>;
|
|
358
358
|
/**
|
|
359
359
|
*
|
|
360
|
-
* @
|
|
360
|
+
* @public
|
|
361
361
|
*/
|
|
362
362
|
declare class KubernetesBuilder {
|
|
363
363
|
protected readonly env: KubernetesEnvironment;
|
|
@@ -397,13 +397,13 @@ declare class KubernetesBuilder {
|
|
|
397
397
|
|
|
398
398
|
/**
|
|
399
399
|
*
|
|
400
|
-
* @
|
|
400
|
+
* @public
|
|
401
401
|
*/
|
|
402
402
|
declare const DEFAULT_OBJECTS: ObjectToFetch[];
|
|
403
403
|
|
|
404
404
|
/**
|
|
405
405
|
*
|
|
406
|
-
* @
|
|
406
|
+
* @public
|
|
407
407
|
*/
|
|
408
408
|
interface RouterOptions {
|
|
409
409
|
logger: Logger;
|
|
@@ -425,7 +425,7 @@ interface RouterOptions {
|
|
|
425
425
|
* }).build();
|
|
426
426
|
* ```
|
|
427
427
|
*
|
|
428
|
-
* @
|
|
428
|
+
* @public
|
|
429
429
|
*/
|
|
430
430
|
declare function createRouter(options: RouterOptions): Promise<express.Router>;
|
|
431
431
|
|
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.9.
|
|
4
|
+
"version": "0.9.4-next.0",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -35,14 +35,13 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@azure/identity": "^2.0.4",
|
|
38
|
-
"@backstage/backend-common": "^0.18.
|
|
39
|
-
"@backstage/
|
|
40
|
-
"@backstage/catalog-
|
|
41
|
-
"@backstage/catalog-model": "^1.2.0-next.1",
|
|
38
|
+
"@backstage/backend-common": "^0.18.3-next.0",
|
|
39
|
+
"@backstage/catalog-client": "^1.4.0-next.0",
|
|
40
|
+
"@backstage/catalog-model": "^1.2.1-next.0",
|
|
42
41
|
"@backstage/config": "^1.0.6",
|
|
43
42
|
"@backstage/errors": "^1.1.4",
|
|
44
|
-
"@backstage/plugin-auth-node": "^0.2.
|
|
45
|
-
"@backstage/plugin-kubernetes-common": "^0.6.
|
|
43
|
+
"@backstage/plugin-auth-node": "^0.2.12-next.0",
|
|
44
|
+
"@backstage/plugin-kubernetes-common": "^0.6.1-next.0",
|
|
46
45
|
"@google-cloud/container": "^4.0.0",
|
|
47
46
|
"@jest-mock/express": "^2.0.1",
|
|
48
47
|
"@kubernetes/client-node": "0.18.1",
|
|
@@ -66,7 +65,8 @@
|
|
|
66
65
|
"yn": "^4.0.0"
|
|
67
66
|
},
|
|
68
67
|
"devDependencies": {
|
|
69
|
-
"@backstage/
|
|
68
|
+
"@backstage/backend-test-utils": "^0.1.35-next.0",
|
|
69
|
+
"@backstage/cli": "^0.22.4-next.0",
|
|
70
70
|
"@types/aws4": "^1.5.1",
|
|
71
71
|
"@types/http-proxy-middleware": "^0.19.3",
|
|
72
72
|
"aws-sdk-mock": "^5.2.1",
|