@orcabus/platform-cdk-constructs 0.0.6 → 0.0.7-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/.jsii +858 -6
  2. package/api-gateway/api-gateway.js +22 -4
  3. package/deployment-stack-pipeline/pipeline.js +6 -4
  4. package/dynamodb/config.d.ts +3 -0
  5. package/dynamodb/config.js +7 -0
  6. package/dynamodb/index.d.ts +27 -0
  7. package/dynamodb/index.js +106 -0
  8. package/ecs/config.d.ts +4 -0
  9. package/ecs/config.js +8 -0
  10. package/ecs/index.d.ts +46 -0
  11. package/ecs/index.js +103 -0
  12. package/index.d.ts +5 -2
  13. package/index.js +47 -5
  14. package/index.ts +16 -2
  15. package/lambda/build_python/Dockerfile +60 -0
  16. package/lambda/config.d.ts +11 -0
  17. package/lambda/config.js +19 -0
  18. package/lambda/index.d.ts +59 -0
  19. package/lambda/index.js +242 -0
  20. package/lambda/layers/mart_tools/poetry.lock +303 -0
  21. package/lambda/layers/mart_tools/pyproject.toml +27 -0
  22. package/lambda/layers/mart_tools/src/mart_tools/__init__.py +0 -0
  23. package/lambda/layers/mart_tools/src/mart_tools/mart/__init__.py +8 -0
  24. package/lambda/layers/mart_tools/src/mart_tools/mart/aws_helpers.py +79 -0
  25. package/lambda/layers/mart_tools/src/mart_tools/mart/dataframe_helpers.py +29 -0
  26. package/lambda/layers/mart_tools/src/mart_tools/mart/globals.py +5 -0
  27. package/lambda/layers/mart_tools/src/mart_tools/mart/models.py +71 -0
  28. package/lambda/layers/orcabus_api_tools/poetry.lock +273 -0
  29. package/lambda/layers/orcabus_api_tools/pyproject.toml +27 -0
  30. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/__init__.py +0 -0
  31. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/__init__.py +172 -0
  32. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/create_helpers.py +47 -0
  33. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/globals.py +13 -0
  34. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/job_helpers.py +53 -0
  35. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/models.py +253 -0
  36. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/query_helpers.py +248 -0
  37. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/update_helpers.py +221 -0
  38. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/workflow_helpers.py +25 -0
  39. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/__init__.py +92 -0
  40. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/create_helpers.py +27 -0
  41. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/globals.py +21 -0
  42. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/models.py +51 -0
  43. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/query_helpers.py +52 -0
  44. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/update_helpers.py +45 -0
  45. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/__init__.py +98 -0
  46. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/errors.py +45 -0
  47. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/file_helpers.py +341 -0
  48. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/globals.py +70 -0
  49. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/models.py +59 -0
  50. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/__init__.py +8 -0
  51. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/aws_helpers.py +79 -0
  52. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/dataframe_helpers.py +29 -0
  53. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/globals.py +5 -0
  54. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/models.py +71 -0
  55. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/__init__.py +250 -0
  56. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/contact_helpers.py +109 -0
  57. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/errors.py +104 -0
  58. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/globals.py +16 -0
  59. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/individual_helpers.py +139 -0
  60. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/library_helpers.py +196 -0
  61. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/lims_helpers.py +36 -0
  62. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/models.py +112 -0
  63. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/project_helpers.py +129 -0
  64. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/sample_helpers.py +132 -0
  65. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/subject_helpers.py +151 -0
  66. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/__init__.py +15 -0
  67. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/globals.py +2 -0
  68. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/models.py +44 -0
  69. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/sequence_helpers.py +62 -0
  70. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/__init__.py +0 -0
  71. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/aws_helpers.py +123 -0
  72. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/miscell.py +17 -0
  73. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/requests_helpers.py +163 -0
  74. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/__init__.py +0 -0
  75. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/errors.py +37 -0
  76. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/metadata_helpers.py +28 -0
  77. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/models.py +85 -0
  78. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/payload_helpers.py +64 -0
  79. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/workflow_run_helpers.py +80 -0
  80. package/package.json +13 -7
  81. package/typedoc.json +3 -0
  82. package/utils/index.d.ts +3 -0
  83. package/utils/index.js +50 -1
package/index.ts CHANGED
@@ -1,3 +1,17 @@
1
- export * as apigateway from "./api-gateway";
2
- export * as deploymentPipeline from "./deployment-stack-pipeline";
1
+ // Get stage name
3
2
  export * as utils from "./utils";
3
+
4
+ // Deployment pipeline constructs
5
+ export * as deploymentPipeline from "./deployment-stack-pipeline";
6
+
7
+ // Api Gateway constructs
8
+ export * as apigateway from "./api-gateway";
9
+
10
+ // DynamoDB Constructs
11
+ export * as dynamodb from "./dynamodb";
12
+
13
+ // ECS / Fargate Constructs
14
+ export * as ecs from "./ecs";
15
+
16
+ // Lambda Constructs
17
+ export * as lambda from "./lambda";
@@ -0,0 +1,60 @@
1
+ # NOTES -
2
+ # THIS IS FROM https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/aws-lambda-python-alpha/lib/Dockerfile
3
+ # We have made the following changes:
4
+ # 1. Added the installation of 'uv'
5
+ # 2. Addded in the UV_CACHE_DIR environment variable
6
+ # 3. Replaced 'pip' with 'uv pip' in the main code chunk
7
+ # 4. Replaced /usr/app/venv/pip with uv pip shell script wrapper
8
+ # The correct AWS SAM build image based on the runtime of the function will be
9
+ # passed as build arg. The default allows to do `docker build .` when testing.
10
+ ARG IMAGE=public.ecr.aws/sam/build-python3.12:latest
11
+ FROM $IMAGE
12
+
13
+ ARG TARGETPLATFORM
14
+ ARG PIP_INDEX_URL
15
+ ARG PIP_EXTRA_INDEX_URL
16
+ ARG HTTPS_PROXY
17
+ ARG POETRY_VERSION=1.5.1
18
+
19
+ # ADDITION: Install uv
20
+ RUN curl -LsSf https://astral.sh/uv/install.sh | XDG_CONFIG_HOME=/tmp UV_INSTALL_DIR=/usr/bin sh
21
+
22
+ # Add virtualenv path
23
+ ENV PATH="/usr/app/venv/bin:$PATH"
24
+
25
+ # set the pip cache location
26
+ ENV PIP_CACHE_DIR=/tmp/pip-cache
27
+
28
+ # set the poetry cache
29
+ ENV POETRY_CACHE_DIR=/tmp/poetry-cache
30
+
31
+ # ADDITION: set the uv cache
32
+ ENV UV_CACHE_DIR=/tmp/uv-cache
33
+
34
+ # ADDITION: Replace 'pip' with uv pip in the following chunk
35
+ RUN \
36
+ # create a new virtualenv for python to use
37
+ # so that it isn't using root
38
+ python -m venv /usr/app/venv && \
39
+ # Create a new location for the pip cache
40
+ mkdir /tmp/pip-cache && \
41
+ # Ensure all users can write to pip cache
42
+ chmod -R 777 /tmp/pip-cache && \
43
+ # Upgrade pip (required by cryptography v3.4 and above, which is a dependency of poetry)
44
+ uv pip install --upgrade pip && \
45
+ # Create a new location for the poetry cache
46
+ mkdir /tmp/poetry-cache && \
47
+ # Ensure all users can write to poetry cache
48
+ chmod -R 777 /tmp/poetry-cache && \
49
+ # Ensure all users can write to uv cache
50
+ chmod -R 777 /tmp/uv-cache && \
51
+ # Install pipenv and poetry
52
+ uv pip install poetry==$POETRY_VERSION && \
53
+ # Ensure no temporary files remain in the caches
54
+ rm -rf /tmp/pip-cache/* /tmp/poetry-cache/* /tmp/uv-cache/*
55
+
56
+ # ADDITION: Replace /usr/app/venv/pip with uv pip
57
+ RUN printf '#!/usr/bin/env bash \nuv pip $@\n' > /usr/app/venv/bin/pip && \
58
+ printf '#!/usr/bin/env bash \nuv pip $@\n' > /usr/app/venv/bin/pip3
59
+
60
+ CMD [ "python" ]
@@ -0,0 +1,11 @@
1
+ import { StageName } from "../utils";
2
+ export declare const DEFAULT_ORCABUS_TOKEN_SECRET_ID = "orcabus/token-service-jwt";
3
+ export declare const DEFAULT_HOSTNAME_SSM_PARAMETER = "/hosted_zone/umccr/name";
4
+ export declare const MART_ENV_VARS: {
5
+ athenaWorkgroupName: string;
6
+ athenaDatasourceName: string;
7
+ athenaDatabaseName: string;
8
+ };
9
+ export declare const MART_S3_BUCKET: Record<StageName, string>;
10
+ export declare const MART_S3_PREFIX = "athena-query-results/";
11
+ export declare const MART_LAMBDA_FUNCTION_NAME = "orcavault";
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MART_LAMBDA_FUNCTION_NAME = exports.MART_S3_PREFIX = exports.MART_S3_BUCKET = exports.MART_ENV_VARS = exports.DEFAULT_HOSTNAME_SSM_PARAMETER = exports.DEFAULT_ORCABUS_TOKEN_SECRET_ID = void 0;
4
+ const utils_1 = require("../utils");
5
+ exports.DEFAULT_ORCABUS_TOKEN_SECRET_ID = 'orcabus/token-service-jwt';
6
+ exports.DEFAULT_HOSTNAME_SSM_PARAMETER = '/hosted_zone/umccr/name';
7
+ exports.MART_ENV_VARS = {
8
+ athenaWorkgroupName: 'orcahouse',
9
+ athenaDatasourceName: 'orcavault',
10
+ athenaDatabaseName: 'mart'
11
+ };
12
+ exports.MART_S3_BUCKET = {
13
+ BETA: `data-sharing-artifacts-${utils_1.accountIdAlias.BETA}-${utils_1.region}`,
14
+ GAMMA: `data-sharing-artifacts-${utils_1.accountIdAlias.GAMMA}-${utils_1.region}`,
15
+ PROD: `data-sharing-artifacts-${utils_1.accountIdAlias.PROD}-${utils_1.region}`
16
+ };
17
+ exports.MART_S3_PREFIX = 'athena-query-results/';
18
+ exports.MART_LAMBDA_FUNCTION_NAME = 'orcavault';
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG9DQUEyRDtBQUU5QyxRQUFBLCtCQUErQixHQUFJLDJCQUEyQixDQUFBO0FBQzlELFFBQUEsOEJBQThCLEdBQUcseUJBQXlCLENBQUE7QUFFMUQsUUFBQSxhQUFhLEdBQUc7SUFDekIsbUJBQW1CLEVBQUUsV0FBVztJQUNoQyxvQkFBb0IsRUFBRSxXQUFXO0lBQ2pDLGtCQUFrQixFQUFFLE1BQU07Q0FDN0IsQ0FBQTtBQUVZLFFBQUEsY0FBYyxHQUE4QjtJQUNyRCxJQUFJLEVBQUUsMEJBQTBCLHNCQUFjLENBQUMsSUFBSSxJQUFJLGNBQU0sRUFBRTtJQUMvRCxLQUFLLEVBQUUsMEJBQTBCLHNCQUFjLENBQUMsS0FBSyxJQUFJLGNBQU0sRUFBRTtJQUNqRSxJQUFJLEVBQUUsMEJBQTBCLHNCQUFjLENBQUMsSUFBSSxJQUFJLGNBQU0sRUFBRTtDQUNsRSxDQUFBO0FBQ1ksUUFBQSxjQUFjLEdBQUcsdUJBQXVCLENBQUE7QUFDeEMsUUFBQSx5QkFBeUIsR0FBRyxXQUFXLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge2FjY291bnRJZEFsaWFzLCByZWdpb24sIFN0YWdlTmFtZX0gZnJvbSBcIi4uL3V0aWxzXCI7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX09SQ0FCVVNfVE9LRU5fU0VDUkVUX0lEID0gICdvcmNhYnVzL3Rva2VuLXNlcnZpY2Utand0J1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfSE9TVE5BTUVfU1NNX1BBUkFNRVRFUiA9ICcvaG9zdGVkX3pvbmUvdW1jY3IvbmFtZSdcblxuZXhwb3J0IGNvbnN0IE1BUlRfRU5WX1ZBUlMgPSB7XG4gICAgYXRoZW5hV29ya2dyb3VwTmFtZTogJ29yY2Fob3VzZScsXG4gICAgYXRoZW5hRGF0YXNvdXJjZU5hbWU6ICdvcmNhdmF1bHQnLFxuICAgIGF0aGVuYURhdGFiYXNlTmFtZTogJ21hcnQnXG59XG5cbmV4cG9ydCBjb25zdCBNQVJUX1MzX0JVQ0tFVDogUmVjb3JkPFN0YWdlTmFtZSwgc3RyaW5nPiA9IHtcbiAgICBCRVRBOiBgZGF0YS1zaGFyaW5nLWFydGlmYWN0cy0ke2FjY291bnRJZEFsaWFzLkJFVEF9LSR7cmVnaW9ufWAsXG4gICAgR0FNTUE6IGBkYXRhLXNoYXJpbmctYXJ0aWZhY3RzLSR7YWNjb3VudElkQWxpYXMuR0FNTUF9LSR7cmVnaW9ufWAsXG4gICAgUFJPRDogYGRhdGEtc2hhcmluZy1hcnRpZmFjdHMtJHthY2NvdW50SWRBbGlhcy5QUk9EfS0ke3JlZ2lvbn1gXG59XG5leHBvcnQgY29uc3QgTUFSVF9TM19QUkVGSVggPSAnYXRoZW5hLXF1ZXJ5LXJlc3VsdHMvJ1xuZXhwb3J0IGNvbnN0IE1BUlRfTEFNQkRBX0ZVTkNUSU9OX05BTUUgPSAnb3JjYXZhdWx0J1xuIl19
@@ -0,0 +1,59 @@
1
+ import { PythonFunction, PythonFunctionProps } from "@aws-cdk/aws-lambda-python-alpha";
2
+ import { Construct } from "constructs";
3
+ export interface OrcabusResourcesProps {
4
+ /**
5
+ * Provide the orcabusTokenSecretId, otherwise it will default to @DEFAULT_ORCABUS_TOKEN_SECRET_ID
6
+ */
7
+ readonly orcabusTokenSecretId?: string;
8
+ /**
9
+ * Provide the hostnameSsmParameterName, otherwise it will default to @DEFAULT_HOSTNAME_SSM_PARAMETER
10
+ */
11
+ readonly hostnameSsmParameterName?: string;
12
+ }
13
+ export interface MartEnvironmentVariables {
14
+ /**
15
+ * Provide the athenaWorkgroupName, otherwise it will default to @MART_ENV_VARS.ATHENA_WORKGROUP_NAME
16
+ */
17
+ readonly athenaWorkgroupName?: string;
18
+ /**
19
+ * Provide the athenaDatasourceName, otherwise it will default to @MART_ENV_VARS.athenaDatasourceName
20
+ */
21
+ readonly athenaDatasourceName?: string;
22
+ /**
23
+ * Provide the athenaDatabaseName, otherwise it will default to @MART_ENV_VARS.ATHENA_DATABASE_NAME
24
+ */
25
+ readonly athenaDatabaseName?: string;
26
+ }
27
+ export interface PythonUvFunctionProps extends PythonFunctionProps {
28
+ /**
29
+ * Whether or not to include the orcabus api tools layer in the lambda function build
30
+ */
31
+ readonly includeOrcabusApiToolsLayer?: boolean;
32
+ /**
33
+ * Whether or not to include the mart layer in the lambda function build
34
+ * Note that the mart layer is a little heavier than the orcabus api tools layer
35
+ * Since we require pandas to be installed
36
+ */
37
+ readonly includeMartLayer?: boolean;
38
+ /**
39
+ * Provide the orcabusTokenResources, optional, otherwise it will default to
40
+ * @DEFAULT_ORCABUS_TOKEN_SECRET_ID and @DEFAULT_HOSTNAME_SSM_PARAMETER
41
+ * for the secret and SSM parameter respectively
42
+ */
43
+ readonly orcabusTokenResources?: OrcabusResourcesProps;
44
+ /**
45
+ * Provide the martEnvironmentVariables, optional, otherwise it will default to
46
+ * @MART_ENV_VARS.ATHENA_WORKGROUP_NAME, @MART_ENV_VARS.ATHENA_DATASOURCE_NAME
47
+ * and @MART_ENV_VARS.ATHENA_DATABASE_NAME for the athena workgroup, datasource and database respectively
48
+ */
49
+ readonly martEnvironmentVariables?: MartEnvironmentVariables;
50
+ }
51
+ export declare class PythonUvFunction extends PythonFunction {
52
+ private static orcabusApiToolsLayer;
53
+ private static martLayer;
54
+ constructor(scope: Construct, id: string, props: PythonUvFunctionProps);
55
+ private buildOrcabusApiToolsLayer;
56
+ private buildMartToolsLayer;
57
+ private setOrcabusResources;
58
+ private setAthenaResources;
59
+ }
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.PythonUvFunction = void 0;
40
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
41
+ const aws_lambda_python_alpha_1 = require("@aws-cdk/aws-lambda-python-alpha");
42
+ const lambda = __importStar(require("aws-cdk-lib/aws-lambda"));
43
+ const secretsManager = __importStar(require("aws-cdk-lib/aws-secretsmanager"));
44
+ const ssm = __importStar(require("aws-cdk-lib/aws-ssm"));
45
+ const iam = __importStar(require("aws-cdk-lib/aws-iam"));
46
+ const s3 = __importStar(require("aws-cdk-lib/aws-s3"));
47
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
48
+ const path_1 = __importDefault(require("path"));
49
+ const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
50
+ const config_1 = require("./config");
51
+ const utils_1 = require("../utils");
52
+ function getPythonUvDockerImage() {
53
+ return aws_cdk_lib_1.DockerImage.fromBuild(path_1.default.join(__dirname, 'build_python'));
54
+ }
55
+ class PythonUvFunction extends aws_lambda_python_alpha_1.PythonFunction {
56
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "@orcabus/platform-cdk-constructs.lambda.PythonUvFunction", version: "0.0.7-alpha.4" };
57
+ // Class constructs, to be used for caching the layers
58
+ // This means that if there are multiple lambdas throughout the stack
59
+ // They will all use the same layer
60
+ static orcabusApiToolsLayer;
61
+ static martLayer;
62
+ constructor(scope, id, props) {
63
+ const uvProps = {
64
+ ...props,
65
+ bundling: {
66
+ ...props.bundling,
67
+ buildArgs: {
68
+ ...props.bundling?.buildArgs,
69
+ // Add TARGETPLATFORM to build args if it's not already set
70
+ TARGETPLATFORM: props.bundling?.buildArgs?.TARGETPLATFORM ?? lambda.Architecture.ARM_64.dockerPlatform,
71
+ },
72
+ image: getPythonUvDockerImage(),
73
+ commandHooks: {
74
+ // @ts-ignore
75
+ beforeBundling(inputDir, outputDir) {
76
+ return [];
77
+ },
78
+ // @ts-ignore
79
+ afterBundling(inputDir, outputDir) {
80
+ return [`rm -rf ${outputDir}/pandas/tests`];
81
+ },
82
+ },
83
+ },
84
+ paramsAndSecrets: props.paramsAndSecrets ??
85
+ aws_lambda_1.ParamsAndSecretsLayerVersion.fromVersion(aws_lambda_1.ParamsAndSecretsVersions.V1_0_103, {
86
+ cacheEnabled: true,
87
+ cacheSize: 300,
88
+ logLevel: aws_lambda_1.ParamsAndSecretsLogLevel.DEBUG,
89
+ }),
90
+ };
91
+ super(scope, id, uvProps);
92
+ if (props.includeOrcabusApiToolsLayer) {
93
+ /* Set the environment variables for the Orcabus resources */
94
+ this.setOrcabusResources(props.orcabusTokenResources ?? {});
95
+ /* Build the orcabus Api tools layer */
96
+ this.buildOrcabusApiToolsLayer();
97
+ this.addLayers(PythonUvFunction.orcabusApiToolsLayer);
98
+ }
99
+ if (props.includeMartLayer) {
100
+ /* Set the environment variables for the mart resources */
101
+ this.setAthenaResources(props.martEnvironmentVariables ?? {});
102
+ /* Build the mart layer */
103
+ this.buildMartToolsLayer();
104
+ this.addLayers(PythonUvFunction.martLayer);
105
+ }
106
+ }
107
+ buildOrcabusApiToolsLayer() {
108
+ // Only build orcabus api layer if it doesn't exist
109
+ if (!PythonUvFunction.orcabusApiToolsLayer) {
110
+ PythonUvFunction.orcabusApiToolsLayer = new aws_lambda_python_alpha_1.PythonLayerVersion(this, 'orcabusApiToolsLayer', {
111
+ layerVersionName: 'orcabusApiToolsLayer',
112
+ entry: path_1.default.join(__dirname, 'layers/orcabus_api_tools'),
113
+ compatibleRuntimes: [lambda.Runtime.PYTHON_3_12],
114
+ compatibleArchitectures: [lambda.Architecture.ARM_64],
115
+ license: 'GPL3',
116
+ description: 'orcabusApiToolsLayer',
117
+ bundling: {
118
+ image: getPythonUvDockerImage(),
119
+ commandHooks: {
120
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
121
+ beforeBundling(inputDir, outputDir) {
122
+ return [];
123
+ },
124
+ afterBundling(inputDir, outputDir) {
125
+ return [
126
+ `pip install ${inputDir} --target ${outputDir}`,
127
+ `find ${outputDir} -name 'pandas' -exec rm -rf {}/tests/ \\;`,
128
+ ];
129
+ },
130
+ },
131
+ },
132
+ });
133
+ }
134
+ }
135
+ buildMartToolsLayer() {
136
+ // Only build the layer if it doesn't exist
137
+ if (!PythonUvFunction.martLayer) {
138
+ PythonUvFunction.martLayer = new aws_lambda_python_alpha_1.PythonLayerVersion(this, 'martToolsLayer', {
139
+ layerVersionName: 'martToolsLayer',
140
+ entry: path_1.default.join(__dirname, 'layers/mart_tools'),
141
+ compatibleRuntimes: [lambda.Runtime.PYTHON_3_12],
142
+ compatibleArchitectures: [lambda.Architecture.ARM_64],
143
+ license: 'GPL3',
144
+ description: 'martToolsLayer',
145
+ bundling: {
146
+ image: getPythonUvDockerImage(),
147
+ commandHooks: {
148
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
149
+ beforeBundling(inputDir, outputDir) {
150
+ return [];
151
+ },
152
+ afterBundling(inputDir, outputDir) {
153
+ return [
154
+ `pip install ${inputDir} --target ${outputDir}`,
155
+ `find ${outputDir} -name 'pandas' -exec rm -rf {}/tests/ \\;`,
156
+ ];
157
+ },
158
+ },
159
+ },
160
+ });
161
+ }
162
+ }
163
+ setOrcabusResources(props) {
164
+ // Set secret object
165
+ const orcabusTokenSecretId = secretsManager.Secret.fromSecretNameV2(this, 'orcabusTokenSecretId', props.orcabusTokenSecretId ?? config_1.DEFAULT_ORCABUS_TOKEN_SECRET_ID);
166
+ const hostnameSsmParameterName = ssm.StringParameter.fromStringParameterName(this, 'hostnameSsmParameterName', props.hostnameSsmParameterName ?? config_1.DEFAULT_HOSTNAME_SSM_PARAMETER);
167
+ // Add permissions for the secret and SSM parameter
168
+ // To the current version
169
+ orcabusTokenSecretId.grantRead(this.currentVersion);
170
+ hostnameSsmParameterName.grantRead(this.currentVersion);
171
+ // Add environment variables
172
+ this.addEnvironment('ORCABUS_TOKEN_SECRET_ID', orcabusTokenSecretId.secretName);
173
+ this.addEnvironment('HOSTNAME_SSM_PARAMETER_NAME', hostnameSsmParameterName.parameterName);
174
+ }
175
+ setAthenaResources(props) {
176
+ // Resolve the stage name by performing a reverse lookup using cdk.Aws.ACCOUNT_ID on accountIdAlias
177
+ const stageName = (0, utils_1.resolveStageName)();
178
+ const athenaS3Bucket = s3.Bucket.fromBucketName(this, 'athenaS3Bucket', config_1.MART_S3_BUCKET[stageName]);
179
+ const athenaFunctionName = lambda.Function.fromFunctionName(this, 'lambdaFunctionName', config_1.MART_LAMBDA_FUNCTION_NAME);
180
+ // Add env vars
181
+ // Iterate over kv pairs of MART_ENV_VARS
182
+ for (const [key, value] of Object.entries(config_1.MART_ENV_VARS)) {
183
+ // After
184
+ if (props[key] !== undefined) {
185
+ this.addEnvironment(key, props[key]);
186
+ }
187
+ else {
188
+ this.addEnvironment(key, value);
189
+ }
190
+ }
191
+ // Permissions
192
+ this.currentVersion.addToRolePolicy(
193
+ // From https://docs.aws.amazon.com/athena/latest/ug/example-policies-workgroup.html
194
+ new iam.PolicyStatement({
195
+ actions: [
196
+ // Workgroup lists
197
+ 'athena:ListEngineVersions',
198
+ 'athena:ListWorkGroups',
199
+ 'athena:ListDataCatalogs',
200
+ 'athena:ListDatabases',
201
+ 'athena:GetDatabase',
202
+ 'athena:ListTableMetadata',
203
+ 'athena:GetTableMetadata',
204
+ 'athena:GetDataCatalog',
205
+ ],
206
+ resources: [`arn:aws:athena:${utils_1.region}:${utils_1.accountIdAlias[stageName]}:*`],
207
+ }));
208
+ this.currentVersion.addToRolePolicy(
209
+ // From https://docs.aws.amazon.com/athena/latest/ug/example-policies-workgroup.html
210
+ new iam.PolicyStatement({
211
+ actions: [
212
+ // Workgroup executions
213
+ 'athena:BatchGetQueryExecution',
214
+ 'athena:GetQueryExecution',
215
+ 'athena:ListQueryExecutions',
216
+ 'athena:StartQueryExecution',
217
+ 'athena:StopQueryExecution',
218
+ 'athena:GetQueryResults',
219
+ 'athena:GetQueryResultsStream',
220
+ 'athena:CreateNamedQuery',
221
+ 'athena:GetNamedQuery',
222
+ 'athena:BatchGetNamedQuery',
223
+ 'athena:ListNamedQueries',
224
+ 'athena:DeleteNamedQuery',
225
+ 'athena:CreatePreparedStatement',
226
+ 'athena:GetPreparedStatement',
227
+ 'athena:ListPreparedStatements',
228
+ 'athena:UpdatePreparedStatement',
229
+ 'athena:DeletePreparedStatement',
230
+ ],
231
+ resources: [
232
+ `arn:aws:athena:${utils_1.region}:${utils_1.accountIdAlias[stageName]}:workgroup/${config_1.MART_ENV_VARS.athenaWorkgroupName}`,
233
+ ],
234
+ }));
235
+ // Add read access to the S3 bucket
236
+ athenaS3Bucket.grantReadWrite(this.currentVersion, `${config_1.MART_S3_PREFIX}*`);
237
+ // Add invoke access to the lambda function
238
+ athenaFunctionName.grantInvoke(this.currentVersion);
239
+ }
240
+ }
241
+ exports.PythonUvFunction = PythonUvFunction;
242
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsOEVBQXlHO0FBRXpHLCtEQUFpRDtBQUNqRCwrRUFBaUU7QUFDakUseURBQTJDO0FBQzNDLHlEQUEyQztBQUMzQyx1REFBeUM7QUFDekMsNkNBQXdDO0FBRXhDLGdEQUF3QjtBQUV4Qix1REFJZ0M7QUFDaEMscUNBTWtCO0FBQ2xCLG9DQUFrRTtBQUdsRSxTQUFTLHNCQUFzQjtJQUMzQixPQUFPLHlCQUFXLENBQUMsU0FBUyxDQUFDLGNBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUM7QUFDdkUsQ0FBQztBQTRERCxNQUFhLGdCQUFpQixTQUFRLHdDQUFjOztJQUNoRCxzREFBc0Q7SUFDdEQscUVBQXFFO0lBQ3JFLG1DQUFtQztJQUMzQixNQUFNLENBQUMsb0JBQW9CLENBQXVCO0lBQ2xELE1BQU0sQ0FBQyxTQUFTLENBQXVCO0lBRS9DLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBNEI7UUFDbEUsTUFBTSxPQUFPLEdBQUc7WUFDWixHQUFHLEtBQUs7WUFDUixRQUFRLEVBQUU7Z0JBQ04sR0FBRyxLQUFLLENBQUMsUUFBUTtnQkFDakIsU0FBUyxFQUFFO29CQUNQLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRSxTQUFTO29CQUM1QiwyREFBMkQ7b0JBQzNELGNBQWMsRUFDVixLQUFLLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxjQUFjLElBQUksTUFBTSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsY0FBYztpQkFDN0Y7Z0JBQ0QsS0FBSyxFQUFFLHNCQUFzQixFQUFFO2dCQUMvQixZQUFZLEVBQUU7b0JBQ1YsYUFBYTtvQkFDYixjQUFjLENBQUMsUUFBZ0IsRUFBRSxTQUFpQjt3QkFDOUMsT0FBTyxFQUFFLENB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QUNELFNBQVMsRUFBRSxDQUFDLGtCQUFrQixjQUFNLElBQUksc0JBQWMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO1NBQ3pFLENBQUMsQ0FDTCxDQUFDO1FBRUYsSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlO1FBQy9CLG9GQUFvRjtRQUNwRixJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7WUFDcEIsT0FBTyxFQUFFO2dCQUNMLHVCQUF1QjtnQkFDdkIsK0JBQStCO2dCQUMvQiwwQkFBMEI7Z0JBQzFCLDRCQUE0QjtnQkFDNUIsNEJBQTRCO2dCQUM1QiwyQkFBMkI7Z0JBQzNCLHdCQUF3QjtnQkFDeEIsOEJBQThCO2dCQUM5Qix5QkFBeUI7Z0JBQ3pCLHNCQUFzQjtnQkFDdEIsMkJBQTJCO2dCQUMzQix5QkFBeUI7Z0JBQ3pCLHlCQUF5QjtnQkFDekIsZ0NBQWdDO2dCQUNoQyw2QkFBNkI7Z0JBQzdCLCtCQUErQjtnQkFDL0IsZ0NBQWdDO2dCQUNoQyxnQ0FBZ0M7YUFDbkM7WUFDRCxTQUFTLEVBQUU7Z0JBQ1Asa0JBQWtCLGNBQU0sSUFBSSxzQkFBYyxDQUFDLFNBQVMsQ0FBQyxjQUFjLHNCQUFhLENBQUMsbUJBQW1CLEVBQUU7YUFDekc7U0FDSixDQUFDLENBQ0wsQ0FBQztRQUVGLG1DQUFtQztRQUNuQyxjQUFjLENBQUMsY0FBYyxDQUN6QixJQUFJLENBQUMsY0FBYyxFQUNuQixHQUFHLHVCQUFjLEdBQUcsQ0FDdkIsQ0FBQTtRQUVELDJDQUEyQztRQUMzQyxrQkFBa0IsQ0FBQyxXQUFXLENBQzFCLElBQUksQ0FBQyxjQUFjLENBQ3RCLENBQUE7SUFDTCxDQUFDOztBQXRPTCw0Q0F1T0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1B5dGhvbkZ1bmN0aW9uLCBQeXRob25GdW5jdGlvblByb3BzLCBQeXRob25MYXllclZlcnNpb259IGZyb20gXCJAYXdzLWNkay9hd3MtbGFtYmRhLXB5dGhvbi1hbHBoYVwiO1xuaW1wb3J0IHtDb25zdHJ1Y3R9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGFcIjtcbmltcG9ydCAqIGFzIHNlY3JldHNNYW5hZ2VyIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc2VjcmV0c21hbmFnZXJcIjtcbmltcG9ydCAqIGFzIHNzbSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXNzbVwiO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQgKiBhcyBzMyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXMzXCI7XG5pbXBvcnQge0RvY2tlckltYWdlfSBmcm9tICdhd3MtY2RrLWxpYic7XG5cbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5cbmltcG9ydCB7XG4gICAgUGFyYW1zQW5kU2VjcmV0c0xheWVyVmVyc2lvbixcbiAgICBQYXJhbXNBbmRTZWNyZXRzTG9nTGV2ZWwsXG4gICAgUGFyYW1zQW5kU2VjcmV0c1ZlcnNpb25zLFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7XG4gICAgREVGQVVMVF9IT1NUTkFNRV9TU01fUEFSQU1FVEVSLFxuICAgIERFRkFVTFRfT1JDQUJVU19UT0tFTl9TRUNSRVRfSUQsXG4gICAgTUFSVF9FTlZfVkFSUywgTUFSVF9MQU1CREFfRlVOQ1RJT05fTkFNRSxcbiAgICBNQVJUX1MzX0JVQ0tFVCxcbiAgICBNQVJUX1MzX1BSRUZJWFxufSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCB7YWNjb3VudElkQWxpYXMsIHJlZ2lvbiwgcmVzb2x2ZVN0YWdlTmFtZX0gZnJvbSBcIi4uL3V0aWxzXCI7XG5cblxuZnVuY3Rpb24gZ2V0UHl0aG9uVXZEb2NrZXJJbWFnZSgpOiBEb2NrZXJJbWFnZSB7XG4gICAgcmV0dXJuIERvY2tlckltYWdlLmZyb21CdWlsZChwYXRoLmpvaW4oX19kaXJuYW1lLCAnYnVpbGRfcHl0aG9uJykpO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9yY2FidXNSZXNvdXJjZXNQcm9wcyB7XG4gICAgLyoqXG4gICAgICogUHJvdmlkZSB0aGUgb3JjYWJ1c1Rva2VuU2VjcmV0SWQsIG90aGVyd2lzZSBpdCB3aWxsIGRlZmF1bHQgdG8gQERFRkFVTFRfT1JDQUJVU19UT0tFTl9TRUNSRVRfSURcbiAgICAgKi9cbiAgICByZWFkb25seSBvcmNhYnVzVG9rZW5TZWNyZXRJZD86IHN0cmluZ1xuXG4gICAgLyoqXG4gICAgICogUHJvdmlkZSB0aGUgaG9zdG5hbWVTc21QYXJhbWV0ZXJOYW1lLCBvdGhlcndpc2UgaXQgd2lsbCBkZWZhdWx0IHRvIEBERUZBVUxUX0hPU1ROQU1FX1NTTV9QQVJBTUVURVJcbiAgICAgKi9cbiAgICByZWFkb25seSBob3N0bmFtZVNzbVBhcmFtZXRlck5hbWU/OiBzdHJpbmdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNYXJ0RW52aXJvbm1lbnRWYXJpYWJsZXMge1xuICAgIC8qKlxuICAgICAqIFByb3ZpZGUgdGhlIGF0aGVuYVdvcmtncm91cE5hbWUsIG90aGVyd2lzZSBpdCB3aWxsIGRlZmF1bHQgdG8gQE1BUlRfRU5WX1ZBUlMuQVRIRU5BX1dPUktHUk9VUF9OQU1FXG4gICAgICovXG4gICAgcmVhZG9ubHkgYXRoZW5hV29ya2dyb3VwTmFtZT86IHN0cmluZ1xuXG4gICAgLyoqXG4gICAgICogUHJvdmlkZSB0aGUgYXRoZW5hRGF0YXNvdXJjZU5hbWUsIG90aGVyd2lzZSBpdCB3aWxsIGRlZmF1bHQgdG8gQE1BUlRfRU5WX1ZBUlMuYXRoZW5hRGF0YXNvdXJjZU5hbWVcbiAgICAgKi9cbiAgICByZWFkb25seSBhdGhlbmFEYXRhc291cmNlTmFtZT86IHN0cmluZ1xuXG4gICAgLyoqXG4gICAgICogUHJvdmlkZSB0aGUgYXRoZW5hRGF0YWJhc2VOYW1lLCBvdGhlcndpc2UgaXQgd2lsbCBkZWZhdWx0IHRvIEBNQVJUX0VOVl9WQVJTLkFUSEVOQV9EQVRBQkFTRV9OQU1FXG4gICAgICovXG4gICAgcmVhZG9ubHkgYXRoZW5hRGF0YWJhc2VOYW1lPzogc3RyaW5nXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHl0aG9uVXZGdW5jdGlvblByb3BzIGV4dGVuZHMgUHl0aG9uRnVuY3Rpb25Qcm9wcyB7XG4gICAgLyoqXG4gICAgICogV2hldGhlciBvciBub3QgdG8gaW5jbHVkZSB0aGUgb3JjYWJ1cyBhcGkgdG9vbHMgbGF5ZXIgaW4gdGhlIGxhbWJkYSBmdW5jdGlvbiBidWlsZFxuICAgICAqL1xuICAgIHJlYWRvbmx5IGluY2x1ZGVPcmNhYnVzQXBpVG9vbHNMYXllcj86IGJvb2xlYW5cblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgb3Igbm90IHRvIGluY2x1ZGUgdGhlIG1hcnQgbGF5ZXIgaW4gdGhlIGxhbWJkYSBmdW5jdGlvbiBidWlsZFxuICAgICAqIE5vdGUgdGhhdCB0aGUgbWFydCBsYXllciBpcyBhIGxpdHRsZSBoZWF2aWVyIHRoYW4gdGhlIG9yY2FidXMgYXBpIHRvb2xzIGxheWVyXG4gICAgICogU2luY2Ugd2UgcmVxdWlyZSBwYW5kYXMgdG8gYmUgaW5zdGFsbGVkXG4gICAgICovXG4gICAgcmVhZG9ubHkgaW5jbHVkZU1hcnRMYXllcj86IGJvb2xlYW5cblxuICAgIC8qKlxuICAgICAqIFByb3ZpZGUgdGhlIG9yY2FidXNUb2tlblJlc291cmNlcywgb3B0aW9uYWwsIG90aGVyd2lzZSBpdCB3aWxsIGRlZmF1bHQgdG9cbiAgICAgKiBAREVGQVVMVF9PUkNBQlVTX1RPS0VOX1NFQ1JFVF9JRCBhbmQgQERFRkFVTFRfSE9TVE5BTUVfU1NNX1BBUkFNRVRFUlxuICAgICAqIGZvciB0aGUgc2VjcmV0IGFuZCBTU00gcGFyYW1ldGVyIHJlc3BlY3RpdmVseVxuICAgICAqL1xuICAgIHJlYWRvbmx5IG9yY2FidXNUb2tlblJlc291cmNlcz86IE9yY2FidXNSZXNvdXJjZXNQcm9wc1xuXG4gICAgLyoqXG4gICAgICogUHJvdmlkZSB0aGUgbWFydEVudmlyb25tZW50VmFyaWFibGVzLCBvcHRpb25hbCwgb3RoZXJ3aXNlIGl0IHdpbGwgZGVmYXVsdCB0b1xuICAgICAqIEBNQVJUX0VOVl9WQVJTLkFUSEVOQV9XT1JLR1JPVVBfTkFNRSwgQE1BUlRfRU5WX1ZBUlMuQVRIRU5BX0RBVEFTT1VSQ0VfTkFNRVxuICAgICAqIGFuZCBATUFSVF9FTlZfVkFSUy5BVEhFTkFfREFUQUJBU0VfTkFNRSBmb3IgdGhlIGF0aGVuYSB3b3JrZ3JvdXAsIGRhdGFzb3VyY2UgYW5kIGRhdGFiYXNlIHJlc3BlY3RpdmVseVxuICAgICAqL1xuICAgIHJlYWRvbmx5IG1hcnRFbnZpcm9ubWVudFZhcmlhYmxlcz86IE1hcnRFbnZpcm9ubWVudFZhcmlhYmxlc1xufVxuXG5cbmV4cG9ydCBjbGFzcyBQeXRob25VdkZ1bmN0aW9uIGV4dGVuZHMgUHl0aG9uRnVuY3Rpb24ge1xuICAgIC8vIENsYXNzIGNvbnN0cnVjdHMsIHRvIGJlIHVzZWQgZm9yIGNhY2hpbmcgdGhlIGxheWVyc1xuICAgIC8vIFRoaXMgbWVhbnMgdGhhdCBpZiB0aGVyZSBhcmUgbXVsdGlwbGUgbGFtYmRhcyB0aHJvdWdob3V0IHRoZSBzdGFja1xuICAgIC8vIFRoZXkgd2lsbCBhbGwgdXNlIHRoZSBzYW1lIGxheWVyXG4gICAgcHJpdmF0ZSBzdGF0aWMgb3JjYWJ1c0FwaVRvb2xzTGF5ZXI6IGxhbWJkYS5JTGF5ZXJWZXJzaW9uO1xuICAgIHByaXZhdGUgc3RhdGljIG1hcnRMYXllcjogbGFtYmRhLklMYXllclZlcnNpb247XG5cbiAgICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogUHl0aG9uVXZGdW5jdGlvblByb3BzKSB7XG4gICAgICAgIGNvbnN0IHV2UHJvcHMgPSB7XG4gICAgICAgICAgICAuLi5wcm9wcyxcbiAgICAgICAgICAgIGJ1bmRsaW5nOiB7XG4gICAgICAgICAgICAgICAgLi4ucHJvcHMuYnVuZGxpbmcsXG4gICAgICAgICAgICAgICAgYnVpbGRBcmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIC4uLnByb3BzLmJ1bmRsaW5nPy5idWlsZEFyZ3MsXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCBUQVJHRVRQTEFURk9STSB0byBidWlsZCBhcmdzIGlmIGl0J3Mgbm90IGFscmVhZHkgc2V0XG4gICAgICAgICAgICAgICAgICAgIFRBUkdFVFBMQVRGT1JNOlxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuYnVuZGxpbmc/LmJ1aWxkQXJncz8uVEFSR0VUUExBVEZPUk0gPz8gbGFtYmRhLkFyY2hpdGVjdHVyZS5BUk1fNjQuZG9ja2VyUGxhdGZvcm0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbWFnZTogZ2V0UHl0aG9uVXZEb2NrZXJJbWFnZSgpLFxuICAgICAgICAgICAgICAgIGNvbW1hbmRIb29rczoge1xuICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgICAgICAgIGJlZm9yZUJ1bmRsaW5nKGlucHV0RGlyOiBzdHJpbmcsIG91dHB1dERpcjogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgICAgICAgIGFmdGVyQnVuZGxpbmcoaW5wdXREaXI6IHN0cmluZywgb3V0cHV0RGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW2BybSAtcmYgJHtvdXRwdXREaXJ9L3BhbmRhcy90ZXN0c2BdO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFyYW1zQW5kU2VjcmV0czpcbiAgICAgICAgICAgICAgICBwcm9wcy5wYXJhbXNBbmRTZWNyZXRzID8/XG4gICAgICAgICAgICAgICAgUGFyYW1zQW5kU2VjcmV0c0xheWVyVmVyc2lvbi5mcm9tVmVyc2lvbihQYXJhbXNBbmRTZWNyZXRzVmVyc2lvbnMuVjFfMF8xMDMsIHtcbiAgICAgICAgICAgICAgICAgICAgY2FjaGVFbmFibGVkOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBjYWNoZVNpemU6IDMwMCxcbiAgICAgICAgICAgICAgICAgICAgbG9nTGV2ZWw6IFBhcmFtc0FuZFNlY3JldHNMb2dMZXZlbC5ERUJVRyxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgfTtcbiAgICAgICAgc3VwZXIoc2NvcGUsIGlkLCB1dlByb3BzKTtcblxuICAgICAgICBpZiAocHJvcHMuaW5jbHVkZU9yY2FidXNBcGlUb29sc0xheWVyKSB7XG4gICAgICAgICAgICAvKiBTZXQgdGhlIGVudmlyb25tZW50IHZhcmlhYmxlcyBmb3IgdGhlIE9yY2FidXMgcmVzb3VyY2VzICovXG4gICAgICAgICAgICB0aGlzLnNldE9yY2FidXNSZXNvdXJjZXMocHJvcHMub3JjYWJ1c1Rva2VuUmVzb3VyY2VzID8/IHt9KVxuXG4gICAgICAgICAgICAvKiBCdWlsZCB0aGUgb3JjYWJ1cyBBcGkgdG9vbHMgbGF5ZXIgKi9cbiAgICAgICAgICAgIHRoaXMuYnVpbGRPcmNhYnVzQXBpVG9vbHNMYXllcigpXG4gICAgICAgICAgICB0aGlzLmFkZExheWVycyhQeXRob25VdkZ1bmN0aW9uLm9yY2FidXNBcGlUb29sc0xheWVyKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByb3BzLmluY2x1ZGVNYXJ0TGF5ZXIpIHtcbiAgICAgICAgICAgIC8qIFNldCB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGVzIGZvciB0aGUgbWFydCByZXNvdXJjZXMgKi9cbiAgICAgICAgICAgIHRoaXMuc2V0QXRoZW5hUmVzb3VyY2VzKHByb3BzLm1hcnRFbnZpcm9ubWVudFZhcmlhYmxlcyA/PyB7fSlcblxuICAgICAgICAgICAgLyogQnVpbGQgdGhlIG1hcnQgbGF5ZXIgKi9cbiAgICAgICAgICAgIHRoaXMuYnVpbGRNYXJ0VG9vbHNMYXllcigpXG4gICAgICAgICAgICB0aGlzLmFkZExheWVycyhQeXRob25VdkZ1bmN0aW9uLm1hcnRMYXllcilcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRPcmNhYnVzQXBpVG9vbHNMYXllcigpIHtcbiAgICAgICAgLy8gT25seSBidWlsZCBvcmNhYnVzIGFwaSBsYXllciBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICAgIGlmICghUHl0aG9uVXZGdW5jdGlvbi5vcmNhYnVzQXBpVG9vbHNMYXllcikge1xuICAgICAgICAgICAgUHl0aG9uVXZGdW5jdGlvbi5vcmNhYnVzQXBpVG9vbHNMYXllciA9IG5ldyBQeXRob25MYXllclZlcnNpb24odGhpcywgJ29yY2FidXNBcGlUb29sc0xheWVyJywge1xuICAgICAgICAgICAgICAgIGxheWVyVmVyc2lvbk5hbWU6ICdvcmNhYnVzQXBpVG9vbHNMYXllcicsXG4gICAgICAgICAgICAgICAgZW50cnk6IHBhdGguam9pbihfX2Rpcm5hbWUsICdsYXllcnMvb3JjYWJ1c19hcGlfdG9vbHMnKSxcbiAgICAgICAgICAgICAgICBjb21wYXRpYmxlUnVudGltZXM6IFtsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMl0sXG4gICAgICAgICAgICAgICAgY29tcGF0aWJsZUFyY2hpdGVjdHVyZXM6IFtsYW1iZGEuQXJjaGl0ZWN0dXJlLkFSTV82NF0sXG4gICAgICAgICAgICAgICAgbGljZW5zZTogJ0dQTDMnLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnb3JjYWJ1c0FwaVRvb2xzTGF5ZXInLFxuICAgICAgICAgICAgICAgIGJ1bmRsaW5nOiB7XG4gICAgICAgICAgICAgICAgICAgIGltYWdlOiBnZXRQeXRob25VdkRvY2tlckltYWdlKCksXG4gICAgICAgICAgICAgICAgICAgIGNvbW1hbmRIb29rczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVmb3JlQnVuZGxpbmcoaW5wdXREaXI6IHN0cmluZywgb3V0cHV0RGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFmdGVyQnVuZGxpbmcoaW5wdXREaXI6IHN0cmluZywgb3V0cHV0RGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYHBpcCBpbnN0YWxsICR7aW5wdXREaXJ9IC0tdGFyZ2V0ICR7b3V0cHV0RGlyfWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBmaW5kICR7b3V0cHV0RGlyfSAtbmFtZSAncGFuZGFzJyAtZXhlYyBybSAtcmYge30vdGVzdHMvIFxcXFw7YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGJ1aWxkTWFydFRvb2xzTGF5ZXIoKSB7XG4gICAgICAgIC8vIE9ubHkgYnVpbGQgdGhlIGxheWVyIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgICAgaWYgKCFQeXRob25VdkZ1bmN0aW9uLm1hcnRMYXllcikge1xuICAgICAgICAgICAgUHl0aG9uVXZGdW5jdGlvbi5tYXJ0TGF5ZXIgPSBuZXcgUHl0aG9uTGF5ZXJWZXJzaW9uKHRoaXMsICdtYXJ0VG9vbHNMYXllcicsIHtcbiAgICAgICAgICAgICAgICBsYXllclZlcnNpb25OYW1lOiAnbWFydFRvb2xzTGF5ZXInLFxuICAgICAgICAgICAgICAgIGVudHJ5OiBwYXRoLmpvaW4oX19kaXJuYW1lLCAnbGF5ZXJzL21hcnRfdG9vbHMnKSxcbiAgICAgICAgICAgICAgICBjb21wYXRpYmxlUnVudGltZXM6IFtsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMl0sXG4gICAgICAgICAgICAgICAgY29tcGF0aWJsZUFyY2hpdGVjdHVyZXM6IFtsYW1iZGEuQXJjaGl0ZWN0dXJlLkFSTV82NF0sXG4gICAgICAgICAgICAgICAgbGljZW5zZTogJ0dQTDMnLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnbWFydFRvb2xzTGF5ZXInLFxuICAgICAgICAgICAgICAgIGJ1bmRsaW5nOiB7XG4gICAgICAgICAgICAgICAgICAgIGltYWdlOiBnZXRQeXRob25VdkRvY2tlckltYWdlKCksXG4gICAgICAgICAgICAgICAgICAgIGNvbW1hbmRIb29rczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgICAgICAgICAgICAgICAgICAgYmVmb3JlQnVuZGxpbmcoaW5wdXREaXI6IHN0cmluZywgb3V0cHV0RGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFmdGVyQnVuZGxpbmcoaW5wdXREaXI6IHN0cmluZywgb3V0cHV0RGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYHBpcCBpbnN0YWxsICR7aW5wdXREaXJ9IC0tdGFyZ2V0ICR7b3V0cHV0RGlyfWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBmaW5kICR7b3V0cHV0RGlyfSAtbmFtZSAncGFuZGFzJyAtZXhlYyBybSAtcmYge30vdGVzdHMvIFxcXFw7YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIHByaXZhdGUgc2V0T3JjYWJ1c1Jlc291cmNlcyhcbiAgICAgICAgcHJvcHM6IE9yY2FidXNSZXNvdXJjZXNQcm9wc1xuICAgICkge1xuICAgICAgICAvLyBTZXQgc2VjcmV0IG9iamVjdFxuICAgICAgICBjb25zdCBvcmNhYnVzVG9rZW5TZWNyZXRJZCA9IHNlY3JldHNNYW5hZ2VyLlNlY3JldC5mcm9tU2VjcmV0TmFtZVYyKFxuICAgICAgICAgICAgdGhpcywgJ29yY2FidXNUb2tlblNlY3JldElkJyxcbiAgICAgICAgICAgIHByb3BzLm9yY2FidXNUb2tlblNlY3JldElkID8/IERFRkFVTFRfT1JDQUJVU19UT0tFTl9TRUNSRVRfSURcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgaG9zdG5hbWVTc21QYXJhbWV0ZXJOYW1lID0gc3NtLlN0cmluZ1BhcmFtZXRlci5mcm9tU3RyaW5nUGFyYW1ldGVyTmFtZShcbiAgICAgICAgICAgIHRoaXMsICdob3N0bmFtZVNzbVBhcmFtZXRlck5hbWUnLFxuICAgICAgICAgICAgcHJvcHMuaG9zdG5hbWVTc21QYXJhbWV0ZXJOYW1lID8/IERFRkFVTFRfSE9TVE5BTUVfU1NNX1BBUkFNRVRFUixcbiAgICAgICAgKVxuXG4gICAgICAgIC8vIEFkZCBwZXJtaXNzaW9ucyBmb3IgdGhlIHNlY3JldCBhbmQgU1NNIHBhcmFtZXRlclxuICAgICAgICAvLyBUbyB0aGUgY3VycmVudCB2ZXJzaW9uXG4gICAgICAgIG9yY2FidXNUb2tlblNlY3JldElkLmdyYW50UmVhZCh0aGlzLmN1cnJlbnRWZXJzaW9uKTtcbiAgICAgICAgaG9zdG5hbWVTc21QYXJhbWV0ZXJOYW1lLmdyYW50UmVhZCh0aGlzLmN1cnJlbnRWZXJzaW9uKVxuXG4gICAgICAgIC8vIEFkZCBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgICAgICAgdGhpcy5hZGRFbnZpcm9ubWVudChcbiAgICAgICAgICAgICdPUkNBQlVTX1RPS0VOX1NFQ1JFVF9JRCcsIG9yY2FidXNUb2tlblNlY3JldElkLnNlY3JldE5hbWUsXG4gICAgICAgIClcbiAgICAgICAgdGhpcy5hZGRFbnZpcm9ubWVudChcbiAgICAgICAgICAgICdIT1NUTkFNRV9TU01fUEFSQU1FVEVSX05BTUUnLCBob3N0bmFtZVNzbVBhcmFtZXRlck5hbWUucGFyYW1ldGVyTmFtZSxcbiAgICAgICAgKVxuICAgIH1cblxuXG4gICAgcHJpdmF0ZSBzZXRBdGhlbmFSZXNvdXJjZXMoXG4gICAgICAgIHByb3BzOiBNYXJ0RW52aXJvbm1lbnRWYXJpYWJsZXNcbiAgICApIHtcbiAgICAgICAgLy8gUmVzb2x2ZSB0aGUgc3RhZ2UgbmFtZSBieSBwZXJmb3JtaW5nIGEgcmV2ZXJzZSBsb29rdXAgdXNpbmcgY2RrLkF3cy5BQ0NPVU5UX0lEIG9uIGFjY291bnRJZEFsaWFzXG4gICAgICAgIGNvbnN0IHN0YWdlTmFtZSA9IHJlc29sdmVTdGFnZU5hbWUoKVxuXG4gICAgICAgIGNvbnN0IGF0aGVuYVMzQnVja2V0ID0gczMuQnVja2V0LmZyb21CdWNrZXROYW1lKFxuICAgICAgICAgICAgdGhpcywgJ2F0aGVuYVMzQnVja2V0JyxcbiAgICAgICAgICAgIE1BUlRfUzNfQlVDS0VUW3N0YWdlTmFtZV1cbiAgICAgICAgKVxuXG4gICAgICAgIGNvbnN0IGF0aGVuYUZ1bmN0aW9uTmFtZSA9IGxhbWJkYS5GdW5jdGlvbi5mcm9tRnVuY3Rpb25OYW1lKFxuICAgICAgICAgICAgdGhpcywgJ2xhbWJkYUZ1bmN0aW9uTmFtZScsIE1BUlRfTEFNQkRBX0ZVTkNUSU9OX05BTUVcbiAgICAgICAgKVxuXG4gICAgICAgIC8vIEFkZCBlbnYgdmFyc1xuICAgICAgICAvLyBJdGVyYXRlIG92ZXIga3YgcGFpcnMgb2YgTUFSVF9FTlZfVkFSU1xuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhNQVJUX0VOVl9WQVJTKSkge1xuICAgICAgICAgICAgLy8gQWZ0ZXJcbiAgICAgICAgICAgIGlmIChwcm9wc1trZXkgYXMga2V5b2YgTWFydEVudmlyb25tZW50VmFyaWFibGVzXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRFbnZpcm9ubWVudChrZXksIHByb3BzW2tleSBhcyBrZXlvZiBNYXJ0RW52aXJvbm1lbnRWYXJpYWJsZXNdISk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkRW52aXJvbm1lbnQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQZXJtaXNzaW9uc1xuICAgICAgICB0aGlzLmN1cnJlbnRWZXJzaW9uLmFkZFRvUm9sZVBvbGljeShcbiAgICAgICAgICAgIC8vIEZyb20gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2F0aGVuYS9sYXRlc3QvdWcvZXhhbXBsZS1wb2xpY2llcy13b3JrZ3JvdXAuaHRtbFxuICAgICAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgICAgICAgICAgLy8gV29ya2dyb3VwIGxpc3RzXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6TGlzdEVuZ2luZVZlcnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpMaXN0V29ya0dyb3VwcycsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6TGlzdERhdGFDYXRhbG9ncycsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6TGlzdERhdGFiYXNlcycsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6R2V0RGF0YWJhc2UnLFxuICAgICAgICAgICAgICAgICAgICAnYXRoZW5hOkxpc3RUYWJsZU1ldGFkYXRhJyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpHZXRUYWJsZU1ldGFkYXRhJyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpHZXREYXRhQ2F0YWxvZycsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICByZXNvdXJjZXM6IFtgYXJuOmF3czphdGhlbmE6JHtyZWdpb259OiR7YWNjb3VudElkQWxpYXNbc3RhZ2VOYW1lXX06KmBdLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmN1cnJlbnRWZXJzaW9uLmFkZFRvUm9sZVBvbGljeShcbiAgICAgICAgICAgIC8vIEZyb20gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2F0aGVuYS9sYXRlc3QvdWcvZXhhbXBsZS1wb2xpY2llcy13b3JrZ3JvdXAuaHRtbFxuICAgICAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgICAgICAgICAgLy8gV29ya2dyb3VwIGV4ZWN1dGlvbnNcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpCYXRjaEdldFF1ZXJ5RXhlY3V0aW9uJyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpHZXRRdWVyeUV4ZWN1dGlvbicsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6TGlzdFF1ZXJ5RXhlY3V0aW9ucycsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6U3RhcnRRdWVyeUV4ZWN1dGlvbicsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6U3RvcFF1ZXJ5RXhlY3V0aW9uJyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpHZXRRdWVyeVJlc3VsdHMnLFxuICAgICAgICAgICAgICAgICAgICAnYXRoZW5hOkdldFF1ZXJ5UmVzdWx0c1N0cmVhbScsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6Q3JlYXRlTmFtZWRRdWVyeScsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6R2V0TmFtZWRRdWVyeScsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6QmF0Y2hHZXROYW1lZFF1ZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpMaXN0TmFtZWRRdWVyaWVzJyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpEZWxldGVOYW1lZFF1ZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpDcmVhdGVQcmVwYXJlZFN0YXRlbWVudCcsXG4gICAgICAgICAgICAgICAgICAgICdhdGhlbmE6R2V0UHJlcGFyZWRTdGF0ZW1lbnQnLFxuICAgICAgICAgICAgICAgICAgICAnYXRoZW5hOkxpc3RQcmVwYXJlZFN0YXRlbWVudHMnLFxuICAgICAgICAgICAgICAgICAgICAnYXRoZW5hOlVwZGF0ZVByZXBhcmVkU3RhdGVtZW50JyxcbiAgICAgICAgICAgICAgICAgICAgJ2F0aGVuYTpEZWxldGVQcmVwYXJlZFN0YXRlbWVudCcsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgYGFybjphd3M6YXRoZW5hOiR7cmVnaW9ufToke2FjY291bnRJZEFsaWFzW3N0YWdlTmFtZV19Ondvcmtncm91cC8ke01BUlRfRU5WX1ZBUlMuYXRoZW5hV29ya2dyb3VwTmFtZX1gLFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIEFkZCByZWFkIGFjY2VzcyB0byB0aGUgUzMgYnVja2V0XG4gICAgICAgIGF0aGVuYVMzQnVja2V0LmdyYW50UmVhZFdyaXRlKFxuICAgICAgICAgICAgdGhpcy5jdXJyZW50VmVyc2lvbixcbiAgICAgICAgICAgIGAke01BUlRfUzNfUFJFRklYfSpgXG4gICAgICAgIClcblxuICAgICAgICAvLyBBZGQgaW52b2tlIGFjY2VzcyB0byB0aGUgbGFtYmRhIGZ1bmN0aW9uXG4gICAgICAgIGF0aGVuYUZ1bmN0aW9uTmFtZS5ncmFudEludm9rZShcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFZlcnNpb25cbiAgICAgICAgKVxuICAgIH1cbn1cblxuXG5cblxuIl19