1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.LinuxGpuBuildImage = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const ecr = require("@aws-cdk/aws-ecr");
|
8 | const core = require("@aws-cdk/core");
|
9 | const region_info_1 = require("@aws-cdk/region-info");
|
10 | const run_script_linux_build_spec_1 = require("./private/run-script-linux-build-spec");
|
11 | const project_1 = require("./project");
|
12 | /**
|
13 | * A CodeBuild GPU image running Linux.
|
14 | *
|
15 | * This class has public constants that represent the most popular GPU images from AWS Deep Learning Containers.
|
16 | *
|
17 | * @see https://aws.amazon.com/releasenotes/available-deep-learning-containers-images
|
18 | */
|
19 | class LinuxGpuBuildImage {
|
20 | constructor(repositoryName, tag, account) {
|
21 | this.repositoryName = repositoryName;
|
22 | this.account = account;
|
23 | this.type = 'LINUX_GPU_CONTAINER';
|
24 | this.defaultComputeType = project_1.ComputeType.LARGE;
|
25 | this.imagePullPrincipalType = project_1.ImagePullPrincipalType.SERVICE_ROLE;
|
26 | const imageAccount = account ?? core.Lazy.string({
|
27 | produce: () => {
|
28 | if (this._imageAccount === undefined) {
|
29 | throw new Error('Make sure this \'LinuxGpuBuildImage\' is used in a CodeBuild Project construct');
|
30 | }
|
31 | return this._imageAccount;
|
32 | },
|
33 | });
|
34 | // The value of imageId below *should* have been `Lazy.stringValue(() => repository.repositoryUriForTag(this.tag))`,
|
35 | // but we can't change that anymore because someone somewhere might at this point have written code
|
36 | // to do `image.imageId.includes('pytorch')` and changing this to a full-on token would break them.
|
37 | this.imageId = `${imageAccount}.dkr.ecr.${core.Aws.REGION}.${core.Aws.URL_SUFFIX}/${repositoryName}:${tag}`;
|
38 | }
|
39 | /**
|
40 | * Returns a Linux GPU build image from AWS Deep Learning Containers.
|
41 | *
|
42 | * @param repositoryName the name of the repository,
|
43 | * for example "pytorch-inference"
|
44 | * @param tag the tag of the image, for example "1.5.0-gpu-py36-cu101-ubuntu16.04"
|
45 | * @param account the AWS account ID where the DLC repository for this region is hosted in.
|
46 | * In many cases, the CDK can infer that for you, but for some newer region our information
|
47 | * might be out of date; in that case, you can specify the region explicitly using this optional parameter
|
48 | * @see https://aws.amazon.com/releasenotes/available-deep-learning-containers-images
|
49 | */
|
50 | static awsDeepLearningContainersImage(repositoryName, tag, account) {
|
51 | return new LinuxGpuBuildImage(repositoryName, tag, account);
|
52 | }
|
53 | /**
|
54 | * Returns a GPU image running Linux from an ECR repository.
|
55 | *
|
56 | * NOTE: if the repository is external (i.e. imported), then we won't be able to add
|
57 | * a resource policy statement for it so CodeBuild can pull the image.
|
58 | *
|
59 | * @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-ecr.html
|
60 | *
|
61 | * @param repository The ECR repository
|
62 | * @param tag Image tag (default "latest")
|
63 | */
|
64 | static fromEcrRepository(repository, tag = 'latest') {
|
65 | return new LinuxGpuBuildImage(repository.repositoryName, tag, repository.env.account);
|
66 | }
|
67 | bind(scope, project, _options) {
|
68 | try {
|
69 | jsiiDeprecationWarnings._aws_cdk_aws_codebuild_IProject(project);
|
70 | jsiiDeprecationWarnings._aws_cdk_aws_codebuild_BuildImageBindOptions(_options);
|
71 | }
|
72 | catch (error) {
|
73 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
74 | Error.captureStackTrace(error, this.bind);
|
75 | }
|
76 | throw error;
|
77 | }
|
78 | const account = this.account ?? core.Stack.of(scope).regionalFact(region_info_1.FactName.DLC_REPOSITORY_ACCOUNT);
|
79 | const repository = ecr.Repository.fromRepositoryAttributes(scope, 'AwsDlcRepositoryCodeBuild', {
|
80 | repositoryName: this.repositoryName,
|
81 | repositoryArn: ecr.Repository.arnForLocalRepository(this.repositoryName, scope, account),
|
82 | });
|
83 | repository.grantPull(project);
|
84 | this._imageAccount = account;
|
85 | return {};
|
86 | }
|
87 | validate(buildEnvironment) {
|
88 | try {
|
89 | jsiiDeprecationWarnings._aws_cdk_aws_codebuild_BuildEnvironment(buildEnvironment);
|
90 | }
|
91 | catch (error) {
|
92 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
93 | Error.captureStackTrace(error, this.validate);
|
94 | }
|
95 | throw error;
|
96 | }
|
97 | const ret = [];
|
98 | if (buildEnvironment.computeType &&
|
99 | buildEnvironment.computeType !== project_1.ComputeType.LARGE) {
|
100 | ret.push(`GPU images only support ComputeType '${project_1.ComputeType.LARGE}' - ` +
|
101 | `'${buildEnvironment.computeType}' was given`);
|
102 | }
|
103 | return ret;
|
104 | }
|
105 | runScriptBuildspec(entrypoint) {
|
106 | return run_script_linux_build_spec_1.runScriptLinuxBuildSpec(entrypoint);
|
107 | }
|
108 | }
|
109 | exports.LinuxGpuBuildImage = LinuxGpuBuildImage;
|
110 | _a = JSII_RTTI_SYMBOL_1;
|
111 | LinuxGpuBuildImage[_a] = { fqn: "@aws-cdk/aws-codebuild.LinuxGpuBuildImage", version: "1.181.1" };
|
112 | /** Tensorflow 1.14.0 GPU image from AWS Deep Learning Containers. */
|
113 | LinuxGpuBuildImage.DLC_TENSORFLOW_1_14_0 = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-training', '1.14.0-gpu-py36-cu100-ubuntu16.04');
|
114 | /** Tensorflow 1.15.0 GPU image from AWS Deep Learning Containers. */
|
115 | LinuxGpuBuildImage.DLC_TENSORFLOW_1_15_0 = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-training', '1.15.0-gpu-py36-cu100-ubuntu18.04');
|
116 | /** Tensorflow 1.15.2 GPU training image from AWS Deep Learning Containers. */
|
117 | LinuxGpuBuildImage.DLC_TENSORFLOW_1_15_2_TRAINING = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-training', '1.15.2-gpu-py37-cu100-ubuntu18.04');
|
118 | /** Tensorflow 1.15.2 GPU inference image from AWS Deep Learning Containers. */
|
119 | LinuxGpuBuildImage.DLC_TENSORFLOW_1_15_2_INFERENCE = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-inference', '1.15.2-gpu-py36-cu100-ubuntu18.04');
|
120 | /** Tensorflow 2.0.0 GPU image from AWS Deep Learning Containers. */
|
121 | LinuxGpuBuildImage.DLC_TENSORFLOW_2_0_0 = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-training', '2.0.0-gpu-py36-cu100-ubuntu18.04');
|
122 | /** Tensorflow 2.0.1 GPU image from AWS Deep Learning Containers. */
|
123 | LinuxGpuBuildImage.DLC_TENSORFLOW_2_0_1 = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-training', '2.0.1-gpu-py36-cu100-ubuntu18.04');
|
124 | /** Tensorflow 2.1.0 GPU training image from AWS Deep Learning Containers. */
|
125 | LinuxGpuBuildImage.DLC_TENSORFLOW_2_1_0_TRAINING = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-training', '2.1.0-gpu-py36-cu101-ubuntu18.04');
|
126 | /** Tensorflow 2.1.0 GPU inference image from AWS Deep Learning Containers. */
|
127 | LinuxGpuBuildImage.DLC_TENSORFLOW_2_1_0_INFERENCE = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-inference', '2.1.0-gpu-py36-cu101-ubuntu18.04');
|
128 | /** Tensorflow 2.2.0 GPU training image from AWS Deep Learning Containers. */
|
129 | LinuxGpuBuildImage.DLC_TENSORFLOW_2_2_0_TRAINING = LinuxGpuBuildImage.awsDeepLearningContainersImage('tensorflow-training', '2.2.0-gpu-py37-cu101-ubuntu18.04');
|
130 | /** PyTorch 1.2.0 GPU image from AWS Deep Learning Containers. */
|
131 | LinuxGpuBuildImage.DLC_PYTORCH_1_2_0 = LinuxGpuBuildImage.awsDeepLearningContainersImage('pytorch-training', '1.2.0-gpu-py36-cu100-ubuntu16.04');
|
132 | /** PyTorch 1.3.1 GPU image from AWS Deep Learning Containers. */
|
133 | LinuxGpuBuildImage.DLC_PYTORCH_1_3_1 = LinuxGpuBuildImage.awsDeepLearningContainersImage('pytorch-training', '1.3.1-gpu-py36-cu101-ubuntu16.04');
|
134 | /** PyTorch 1.4.0 GPU training image from AWS Deep Learning Containers. */
|
135 | LinuxGpuBuildImage.DLC_PYTORCH_1_4_0_TRAINING = LinuxGpuBuildImage.awsDeepLearningContainersImage('pytorch-training', '1.4.0-gpu-py36-cu101-ubuntu16.04');
|
136 | /** PyTorch 1.4.0 GPU inference image from AWS Deep Learning Containers. */
|
137 | LinuxGpuBuildImage.DLC_PYTORCH_1_4_0_INFERENCE = LinuxGpuBuildImage.awsDeepLearningContainersImage('pytorch-inference', '1.4.0-gpu-py36-cu101-ubuntu16.04');
|
138 | /** PyTorch 1.5.0 GPU training image from AWS Deep Learning Containers. */
|
139 | LinuxGpuBuildImage.DLC_PYTORCH_1_5_0_TRAINING = LinuxGpuBuildImage.awsDeepLearningContainersImage('pytorch-training', '1.5.0-gpu-py36-cu101-ubuntu16.04');
|
140 | /** PyTorch 1.5.0 GPU inference image from AWS Deep Learning Containers. */
|
141 | LinuxGpuBuildImage.DLC_PYTORCH_1_5_0_INFERENCE = LinuxGpuBuildImage.awsDeepLearningContainersImage('pytorch-inference', '1.5.0-gpu-py36-cu101-ubuntu16.04');
|
142 | /** MXNet 1.4.1 GPU image from AWS Deep Learning Containers. */
|
143 | LinuxGpuBuildImage.DLC_MXNET_1_4_1 = LinuxGpuBuildImage.awsDeepLearningContainersImage('mxnet-training', '1.4.1-gpu-py36-cu100-ubuntu16.04');
|
144 | /** MXNet 1.6.0 GPU image from AWS Deep Learning Containers. */
|
145 | LinuxGpuBuildImage.DLC_MXNET_1_6_0 = LinuxGpuBuildImage.awsDeepLearningContainersImage('mxnet-training', '1.6.0-gpu-py36-cu101-ubuntu16.04');
|
146 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGludXgtZ3B1LWJ1aWxkLWltYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibGludXgtZ3B1LWJ1aWxkLWltYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHdDQUF3QztBQUN4QyxzQ0FBc0M7QUFDdEMsc0RBQWdEO0FBRWhELHVGQUFnRjtBQUNoRix1Q0FHbUI7QUFNbkI7Ozs7OztHQU1HO0FBQ0gsTUFBYSxrQkFBa0I7SUE2RjdCLFlBQXFDLGNBQXNCLEVBQUUsR0FBVyxFQUFtQixPQUEyQjtRQUFqRixtQkFBYyxHQUFkLGNBQWMsQ0FBUTtRQUFnQyxZQUFPLEdBQVAsT0FBTyxDQUFvQjtRQVB0RyxTQUFJLEdBQUcscUJBQXFCLENBQUM7UUFDN0IsdUJBQWtCLEdBQUcscUJBQVcsQ0FBQyxLQUFLLENBQUM7UUFDdkMsMkJBQXNCLEdBQTRCLGdDQUFzQixDQUFDLFlBQVksQ0FBQztRQU1wRyxNQUFNLFlBQVksR0FBRyxPQUFPLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDL0MsT0FBTyxFQUFFLEdBQUcsRUFBRTtnQkFDWixJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssU0FBUyxFQUFFO29CQUNwQyxNQUFNLElBQUksS0FBSyxDQUFDLGdGQUFnRixDQUFDLENBQUM7aUJBQ25HO2dCQUNELE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQztZQUM1QixDQUFDO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsb0hBQW9IO1FBQ3BILG1HQUFtRztRQUNuRyxtR0FBbUc7UUFDbkcsSUFBSSxDQUFDLE9BQU8sR0FBRyxHQUFHLFlBQVksWUFBWSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxjQUFjLElBQUksR0FBRyxFQUFFLENBQUM7S0FDN0c7SUFwREQ7Ozs7Ozs7Ozs7T0FVRztJQUNJLE1BQU0sQ0FBQyw4QkFBOEIsQ0FBQyxjQUFzQixFQUFFLEdBQVcs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QWtCLENBQUMsOEJBQThCLENBQUMscUJBQXFCLEVBQzVILGtDQUFrQyxDQUFDLENBQUM7QUFFdEMsaUVBQWlFO0FBQzFDLG9DQUFpQixHQUFHLGtCQUFrQixDQUFDLDhCQUE4QixDQUFDLGtCQUFrQixFQUM3RyxrQ0FBa0MsQ0FBQyxDQUFDO0FBQ3RDLGlFQUFpRTtBQUMxQyxvQ0FBaUIsR0FBRyxrQkFBa0IsQ0FBQyw4QkFBOEIsQ0FBQyxrQkFBa0IsRUFDN0csa0NBQWtDLENBQUMsQ0FBQztBQUN0QywwRUFBMEU7QUFDbkQsNkNBQTBCLEdBQUcsa0JBQWtCLENBQUMsOEJBQThCLENBQUMsa0JBQWtCLEVBQ3RILGtDQUFrQyxDQUFDLENBQUM7QUFDdEMsMkVBQTJFO0FBQ3BELDhDQUEyQixHQUFHLGtCQUFrQixDQUFDLDhCQUE4QixDQUFDLG1CQUFtQixFQUN4SCxrQ0FBa0MsQ0FBQyxDQUFDO0FBQ3RDLDBFQUEwRTtBQUNuRCw2Q0FBMEIsR0FBRyxrQkFBa0IsQ0FBQyw4QkFBOEIsQ0FBQyxrQkFBa0IsRUFDdEgsa0NBQWtDLENBQUMsQ0FBQztBQUN0QywyRUFBMkU7QUFDcEQsOENBQTJCLEdBQUcsa0JBQWtCLENBQUMsOEJBQThCLENBQUMsbUJBQW1CLEVBQ3hILGtDQUFrQyxDQUFDLENBQUM7QUFFdEMsK0RBQStEO0FBQ3hDLGtDQUFlLEdBQUcsa0JBQWtCLENBQUMsOEJBQThCLENBQUMsZ0JBQWdCLEVBQ3pHLGtDQUFrQyxDQUFDLENBQUM7QUFDdEMsK0RBQStEO0FBQ3hDLGtDQUFlLEdBQUcsa0JBQWtCLENBQUMsOEJBQThCLENBQUMsZ0JBQWdCLEVBQ3pHLGtDQUFrQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBlY3IgZnJvbSAnQGF3cy1jZGsvYXdzLWVjcic7XG5pbXBvcnQgKiBhcyBjb3JlIGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgRmFjdE5hbWUgfSBmcm9tICdAYXdzLWNkay9yZWdpb24taW5mbyc7XG5pbXBvcnQgeyBCdWlsZFNwZWMgfSBmcm9tICcuL2J1aWxkLXNwZWMnO1xuaW1wb3J0IHsgcnVuU2NyaXB0TGludXhCdWlsZFNwZWMgfSBmcm9tICcuL3ByaXZhdGUvcnVuLXNjcmlwdC1saW51eC1idWlsZC1zcGVjJztcbmltcG9ydCB7XG4gIEJ1aWxkRW52aXJvbm1lbnQsIEJ1aWxkSW1hZ2VCaW5kT3B0aW9ucywgQnVpbGRJbWFnZUNvbmZpZywgQ29tcHV0ZVR5cGUsIElCaW5kYWJsZUJ1aWxkSW1hZ2UsIElCdWlsZEltYWdlLFxuICBJbWFnZVB1bGxQcmluY2lwYWxUeXBlLCBJUHJvamVjdCxcbn0gZnJvbSAnLi9wcm9qZWN0JztcblxuLy8ga2VlcCB0aGlzIGltcG9ydCBzZXBhcmF0ZSBmcm9tIG90aGVyIGltcG9ydHMgdG8gcmVkdWNlIGNoYW5jZSBmb3IgbWVyZ2UgY29uZmxpY3RzIHdpdGggdjItbWFpblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWR1cGxpY2F0ZS1pbXBvcnRzLCBpbXBvcnQvb3JkZXJcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuXG4vKipcbiAqIEEgQ29kZUJ1aWxkIEdQVSBpbWFnZSBydW5uaW5nIExpbnV4LlxuICpcbiAqIFRoaXMgY2xhc3MgaGFzIHB1YmxpYyBjb25zdGFudHMgdGhhdCByZXByZXNlbnQgdGhlIG1vc3QgcG9wdWxhciBHUFUgaW1hZ2VzIGZyb20gQVdTIERlZXAgTGVhcm5pbmcgQ29udGFpbmVycy5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vYXdzLmFtYXpvbi5jb20vcmVsZWFzZW5vdGVzL2F2YWlsYWJsZS1kZWVwLWxlYXJuaW5nLWNvbnRhaW5lcnMtaW1hZ2VzXG4gKi9cbmV4cG9ydCBjbGFzcyBMaW51eEdwdUJ1aWxkSW1hZ2UgaW1wbGVtZW50cyBJQmluZGFibGVCdWlsZEltYWdlIHtcbiAgLyoqIFRlbnNvcmZsb3cgMS4xNC4wIEdQVSBpbWFnZSBmcm9tIEFXUyBEZWVwIExlYXJuaW5nIENvbnRhaW5lcnMuICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgRExDX1RFTlNPUkZMT1dfMV8xNF8wID0gTGludXhHcHVCdWlsZEltYWdlLmF3c0RlZXBMZWFybmluZ0NvbnRhaW5lcnNJbWFnZSgndGVuc29yZmxvdy10cmFpbmluZycsXG4gICAgJzEuMTQuMC1ncHUtcHkzNi1jdTEwMC11YnVudHUxNi4wNCcpO1xuICAvKiogVGVuc29yZmxvdyAxLjE1LjAgR1BVIGltYWdlIGZyb20gQVdTIERlZXAgTGVhcm5pbmcgQ29udGFpbmVycy4gKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBETENfVEVOU09SRkxPV18xXzE1XzAgPSBMaW51eEdwdUJ1aWxkSW1hZ2UuYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKCd0ZW5zb3JmbG93LXRyYWluaW5nJyxcbiAgICAnMS4xNS4wLWdwdS1weTM2LWN1MTAwLXVidW50dTE4LjA0Jyk7XG4gIC8qKiBUZW5zb3JmbG93IDEuMTUuMiBHUFUgdHJhaW5pbmcgaW1hZ2UgZnJvbSBBV1MgRGVlcCBMZWFybmluZyBDb250YWluZXJzLiAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERMQ19URU5TT1JGTE9XXzFfMTVfMl9UUkFJTklORyA9IExpbnV4R3B1QnVpbGRJbWFnZS5hd3NEZWVwTGVhcm5pbmdDb250YWluZXJzSW1hZ2UoJ3RlbnNvcmZsb3ctdHJhaW5pbmcnLFxuICAgICcxLjE1LjItZ3B1LXB5MzctY3UxMDAtdWJ1bnR1MTguMDQnKTtcbiAgLyoqIFRlbnNvcmZsb3cgMS4xNS4yIEdQVSBpbmZlcmVuY2UgaW1hZ2UgZnJvbSBBV1MgRGVlcCBMZWFybmluZyBDb250YWluZXJzLiAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERMQ19URU5TT1JGTE9XXzFfMTVfMl9JTkZFUkVOQ0UgPSBMaW51eEdwdUJ1aWxkSW1hZ2UuYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKCd0ZW5zb3JmbG93LWluZmVyZW5jZScsXG4gICAgJzEuMTUuMi1ncHUtcHkzNi1jdTEwMC11YnVudHUxOC4wNCcpO1xuICAvKiogVGVuc29yZmxvdyAyLjAuMCBHUFUgaW1hZ2UgZnJvbSBBV1MgRGVlcCBMZWFybmluZyBDb250YWluZXJzLiAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERMQ19URU5TT1JGTE9XXzJfMF8wID0gTGludXhHcHVCdWlsZEltYWdlLmF3c0RlZXBMZWFybmluZ0NvbnRhaW5lcnNJbWFnZSgndGVuc29yZmxvdy10cmFpbmluZycsXG4gICAgJzIuMC4wLWdwdS1weTM2LWN1MTAwLXVidW50dTE4LjA0Jyk7XG4gIC8qKiBUZW5zb3JmbG93IDIuMC4xIEdQVSBpbWFnZSBmcm9tIEFXUyBEZWVwIExlYXJuaW5nIENvbnRhaW5lcnMuICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgRExDX1RFTlNPUkZMT1dfMl8wXzEgPSBMaW51eEdwdUJ1aWxkSW1hZ2UuYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKCd0ZW5zb3JmbG93LXRyYWluaW5nJyxcbiAgICAnMi4wLjEtZ3B1LXB5MzYtY3UxMDAtdWJ1bnR1MTguMDQnKTtcbiAgLyoqIFRlbnNvcmZsb3cgMi4xLjAgR1BVIHRyYWluaW5nIGltYWdlIGZyb20gQVdTIERlZXAgTGVhcm5pbmcgQ29udGFpbmVycy4gKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBETENfVEVOU09SRkxPV18yXzFfMF9UUkFJTklORyA9IExpbnV4R3B1QnVpbGRJbWFnZS5hd3NEZWVwTGVhcm5pbmdDb250YWluZXJzSW1hZ2UoJ3RlbnNvcmZsb3ctdHJhaW5pbmcnLFxuICAgICcyLjEuMC1ncHUtcHkzNi1jdTEwMS11YnVudHUxOC4wNCcpO1xuICAvKiogVGVuc29yZmxvdyAyLjEuMCBHUFUgaW5mZXJlbmNlIGltYWdlIGZyb20gQVdTIERlZXAgTGVhcm5pbmcgQ29udGFpbmVycy4gKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBETENfVEVOU09SRkxPV18yXzFfMF9JTkZFUkVOQ0UgPSBMaW51eEdwdUJ1aWxkSW1hZ2UuYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKCd0ZW5zb3JmbG93LWluZmVyZW5jZScsXG4gICAgJzIuMS4wLWdwdS1weTM2LWN1MTAxLXVidW50dTE4LjA0Jyk7XG4gIC8qKiBUZW5zb3JmbG93IDIuMi4wIEdQVSB0cmFpbmluZyBpbWFnZSBmcm9tIEFXUyBEZWVwIExlYXJuaW5nIENvbnRhaW5lcnMuICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgRExDX1RFTlNPUkZMT1dfMl8yXzBfVFJBSU5JTkcgPSBMaW51eEdwdUJ1aWxkSW1hZ2UuYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKCd0ZW5zb3JmbG93LXRyYWluaW5nJyxcbiAgICAnMi4yLjAtZ3B1LXB5MzctY3UxMDEtdWJ1bnR1MTguMDQnKTtcblxuICAvKiogUHlUb3JjaCAxLjIuMCBHUFUgaW1hZ2UgZnJvbSBBV1MgRGVlcCBMZWFybmluZyBDb250YWluZXJzLiAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERMQ19QWVRPUkNIXzFfMl8wID0gTGludXhHcHVCdWlsZEltYWdlLmF3c0RlZXBMZWFybmluZ0NvbnRhaW5lcnNJbWFnZSgncHl0b3JjaC10cmFpbmluZycsXG4gICAgJzEuMi4wLWdwdS1weTM2LWN1MTAwLXVidW50dTE2LjA0Jyk7XG4gIC8qKiBQeVRvcmNoIDEuMy4xIEdQVSBpbWFnZSBmcm9tIEFXUyBEZWVwIExlYXJuaW5nIENvbnRhaW5lcnMuICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgRExDX1BZVE9SQ0hfMV8zXzEgPSBMaW51eEdwdUJ1aWxkSW1hZ2UuYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKCdweXRvcmNoLXRyYWluaW5nJyxcbiAgICAnMS4zLjEtZ3B1LXB5MzYtY3UxMDEtdWJ1bnR1MTYuMDQnKTtcbiAgLyoqIFB5VG9yY2ggMS40LjAgR1BVIHRyYWluaW5nIGltYWdlIGZyb20gQVdTIERlZXAgTGVhcm5pbmcgQ29udGFpbmVycy4gKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBETENfUFlUT1JDSF8xXzRfMF9UUkFJTklORyA9IExpbnV4R3B1QnVpbGRJbWFnZS5hd3NEZWVwTGVhcm5pbmdDb250YWluZXJzSW1hZ2UoJ3B5dG9yY2gtdHJhaW5pbmcnLFxuICAgICcxLjQuMC1ncHUtcHkzNi1jdTEwMS11YnVudHUxNi4wNCcpO1xuICAvKiogUHlUb3JjaCAxLjQuMCBHUFUgaW5mZXJlbmNlIGltYWdlIGZyb20gQVdTIERlZXAgTGVhcm5pbmcgQ29udGFpbmVycy4gKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBETENfUFlUT1JDSF8xXzRfMF9JTkZFUkVOQ0UgPSBMaW51eEdwdUJ1aWxkSW1hZ2UuYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKCdweXRvcmNoLWluZmVyZW5jZScsXG4gICAgJzEuNC4wLWdwdS1weTM2LWN1MTAxLXVidW50dTE2LjA0Jyk7XG4gIC8qKiBQeVRvcmNoIDEuNS4wIEdQVSB0cmFpbmluZyBpbWFnZSBmcm9tIEFXUyBEZWVwIExlYXJuaW5nIENvbnRhaW5lcnMuICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgRExDX1BZVE9SQ0hfMV81XzBfVFJBSU5JTkcgPSBMaW51eEdwdUJ1aWxkSW1hZ2UuYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKCdweXRvcmNoLXRyYWluaW5nJyxcbiAgICAnMS41LjAtZ3B1LXB5MzYtY3UxMDEtdWJ1bnR1MTYuMDQnKTtcbiAgLyoqIFB5VG9yY2ggMS41LjAgR1BVIGluZmVyZW5jZSBpbWFnZSBmcm9tIEFXUyBEZWVwIExlYXJuaW5nIENvbnRhaW5lcnMuICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgRExDX1BZVE9SQ0hfMV81XzBfSU5GRVJFTkNFID0gTGludXhHcHVCdWlsZEltYWdlLmF3c0RlZXBMZWFybmluZ0NvbnRhaW5lcnNJbWFnZSgncHl0b3JjaC1pbmZlcmVuY2UnLFxuICAgICcxLjUuMC1ncHUtcHkzNi1jdTEwMS11YnVudHUxNi4wNCcpO1xuXG4gIC8qKiBNWE5ldCAxLjQuMSBHUFUgaW1hZ2UgZnJvbSBBV1MgRGVlcCBMZWFybmluZyBDb250YWluZXJzLiAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERMQ19NWE5FVF8xXzRfMSA9IExpbnV4R3B1QnVpbGRJbWFnZS5hd3NEZWVwTGVhcm5pbmdDb250YWluZXJzSW1hZ2UoJ214bmV0LXRyYWluaW5nJyxcbiAgICAnMS40LjEtZ3B1LXB5MzYtY3UxMDAtdWJ1bnR1MTYuMDQnKTtcbiAgLyoqIE1YTmV0IDEuNi4wIEdQVSBpbWFnZSBmcm9tIEFXUyBEZWVwIExlYXJuaW5nIENvbnRhaW5lcnMuICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgRExDX01YTkVUXzFfNl8wID0gTGludXhHcHVCdWlsZEltYWdlLmF3c0RlZXBMZWFybmluZ0NvbnRhaW5lcnNJbWFnZSgnbXhuZXQtdHJhaW5pbmcnLFxuICAgICcxLjYuMC1ncHUtcHkzNi1jdTEwMS11YnVudHUxNi4wNCcpO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgTGludXggR1BVIGJ1aWxkIGltYWdlIGZyb20gQVdTIERlZXAgTGVhcm5pbmcgQ29udGFpbmVycy5cbiAgICpcbiAgICogQHBhcmFtIHJlcG9zaXRvcnlOYW1lIHRoZSBuYW1lIG9mIHRoZSByZXBvc2l0b3J5LFxuICAgKiAgIGZvciBleGFtcGxlIFwicHl0b3JjaC1pbmZlcmVuY2VcIlxuICAgKiBAcGFyYW0gdGFnIHRoZSB0YWcgb2YgdGhlIGltYWdlLCBmb3IgZXhhbXBsZSBcIjEuNS4wLWdwdS1weTM2LWN1MTAxLXVidW50dTE2LjA0XCJcbiAgICogQHBhcmFtIGFjY291bnQgdGhlIEFXUyBhY2NvdW50IElEIHdoZXJlIHRoZSBETEMgcmVwb3NpdG9yeSBmb3IgdGhpcyByZWdpb24gaXMgaG9zdGVkIGluLlxuICAgKiAgIEluIG1hbnkgY2FzZXMsIHRoZSBDREsgY2FuIGluZmVyIHRoYXQgZm9yIHlvdSwgYnV0IGZvciBzb21lIG5ld2VyIHJlZ2lvbiBvdXIgaW5mb3JtYXRpb25cbiAgICogICBtaWdodCBiZSBvdXQgb2YgZGF0ZTsgaW4gdGhhdCBjYXNlLCB5b3UgY2FuIHNwZWNpZnkgdGhlIHJlZ2lvbiBleHBsaWNpdGx5IHVzaW5nIHRoaXMgb3B0aW9uYWwgcGFyYW1ldGVyXG4gICAqIEBzZWUgaHR0cHM6Ly9hd3MuYW1hem9uLmNvbS9yZWxlYXNlbm90ZXMvYXZhaWxhYmxlLWRlZXAtbGVhcm5pbmctY29udGFpbmVycy1pbWFnZXNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYXdzRGVlcExlYXJuaW5nQ29udGFpbmVyc0ltYWdlKHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcsIHRhZzogc3RyaW5nLCBhY2NvdW50Pzogc3RyaW5nKTogSUJ1aWxkSW1hZ2Uge1xuICAgIHJldHVybiBuZXcgTGludXhHcHVCdWlsZEltYWdlKHJlcG9zaXRvcnlOYW1lLCB0YWcsIGFjY291bnQpO1xuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBhIEdQVSBpbWFnZSBydW5uaW5nIExpbnV4IGZyb20gYW4gRUNSIHJlcG9zaXRvcnkuXG4gICAqXG4gICAqIE5PVEU6IGlmIHRoZSByZXBvc2l0b3J5IGlzIGV4dGVybmFsIChpLmUuIGltcG9ydGVkKSwgdGhlbiB3ZSB3b24ndCBiZSBhYmxlIHRvIGFkZFxuICAgKiBhIHJlc291cmNlIHBvbGljeSBzdGF0ZW1lbnQgZm9yIGl0IHNvIENvZGVCdWlsZCBjYW4gcHVsbCB0aGUgaW1hZ2UuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2NvZGVidWlsZC9sYXRlc3QvdXNlcmd1aWRlL3NhbXBsZS1lY3IuaHRtbFxuICAgKlxuICAgKiBAcGFyYW0gcmVwb3NpdG9yeSBUaGUgRUNSIHJlcG9zaXRvcnlcbiAgICogQHBhcmFtIHRhZyBJbWFnZSB0YWcgKGRlZmF1bHQgXCJsYXRlc3RcIilcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUVjclJlcG9zaXRvcnkocmVwb3NpdG9yeTogZWNyLklSZXBvc2l0b3J5LCB0YWc6IHN0cmluZyA9ICdsYXRlc3QnKTogSUJ1aWxkSW1hZ2Uge1xuICAgIHJldHVybiBuZXcgTGludXhHcHVCdWlsZEltYWdlKHJlcG9zaXRvcnkucmVwb3NpdG9yeU5hbWUsIHRhZywgcmVwb3NpdG9yeS5lbnYuYWNjb3VudCk7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgdHlwZSA9ICdMSU5VWF9HUFVfQ09OVEFJTkVSJztcbiAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRDb21wdXRlVHlwZSA9IENvbXB1dGVUeXBlLkxBUkdFO1xuICBwdWJsaWMgcmVhZG9ubHkgaW1hZ2VQdWxsUHJpbmNpcGFsVHlwZT86IEltYWdlUHVsbFByaW5jaXBhbFR5cGUgPSBJbWFnZVB1bGxQcmluY2lwYWxUeXBlLlNFUlZJQ0VfUk9MRTtcbiAgcHVibGljIHJlYWRvbmx5IGltYWdlSWQ6IHN0cmluZztcblxuICBwcml2YXRlIF9pbWFnZUFjY291bnQ/OiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcsIHRhZzogc3RyaW5nLCBwcml2YXRlIHJlYWRvbmx5IGFjY291bnQ6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IGltYWdlQWNjb3VudCA9IGFjY291bnQgPz8gY29yZS5MYXp5LnN0cmluZyh7XG4gICAgICBwcm9kdWNlOiAoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLl9pbWFnZUFjY291bnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWFrZSBzdXJlIHRoaXMgXFwnTGludXhHcHVCdWlsZEltYWdlXFwnIGlzIHVzZWQgaW4gYSBDb2RlQnVpbGQgUHJvamVjdCBjb25zdHJ1Y3QnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5faW1hZ2VBY2NvdW50O1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIFRoZSB2YWx1ZSBvZiBpbWFnZUlkIGJlbG93ICpzaG91bGQqIGhhdmUgYmVlbiBgTGF6eS5zdHJpbmdWYWx1ZSgoKSA9PiByZXBvc2l0b3J5LnJlcG9zaXRvcnlVcmlGb3JUYWcodGhpcy50YWcpKWAsXG4gICAgLy8gYnV0IHdlIGNhbid0IGNoYW5nZSB0aGF0IGFueW1vcmUgYmVjYXVzZSBzb21lb25lIHNvbWV3aGVyZSBtaWdodCBhdCB0aGlzIHBvaW50IGhhdmUgd3JpdHRlbiBjb2RlXG4gICAgLy8gdG8gZG8gYGltYWdlLmltYWdlSWQuaW5jbHVkZXMoJ3B5dG9yY2gnKWAgYW5kIGNoYW5naW5nIHRoaXMgdG8gYSBmdWxsLW9uIHRva2VuIHdvdWxkIGJyZWFrIHRoZW0uXG4gICAgdGhpcy5pbWFnZUlkID0gYCR7aW1hZ2VBY2NvdW50fS5ka3IuZWNyLiR7Y29yZS5Bd3MuUkVHSU9OfS4ke2NvcmUuQXdzLlVSTF9TVUZGSVh9LyR7cmVwb3NpdG9yeU5hbWV9OiR7dGFnfWA7XG4gIH1cblxuICBwdWJsaWMgYmluZChzY29wZTogQ29uc3RydWN0LCBwcm9qZWN0OiBJUHJvamVjdCwgX29wdGlvbnM6IEJ1aWxkSW1hZ2VCaW5kT3B0aW9ucyk6IEJ1aWxkSW1hZ2VDb25maWcge1xuICAgIGNvbnN0IGFjY291bnQgPSB0aGlzLmFjY291bnQgPz8gY29yZS5TdGFjay5vZihzY29wZSkucmVnaW9uYWxGYWN0KEZhY3ROYW1lLkRMQ19SRVBPU0lUT1JZX0FDQ09VTlQpO1xuICAgIGNvbnN0IHJlcG9zaXRvcnkgPSBlY3IuUmVwb3NpdG9yeS5mcm9tUmVwb3NpdG9yeUF0dHJpYnV0ZXMoc2NvcGUsICdBd3NEbGNSZXBvc2l0b3J5Q29kZUJ1aWxkJywge1xuICAgICAgcmVwb3NpdG9yeU5hbWU6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICByZXBvc2l0b3J5QXJuOiBlY3IuUmVwb3NpdG9yeS5hcm5Gb3JMb2NhbFJlcG9zaXRvcnkodGhpcy5yZXBvc2l0b3J5TmFtZSwgc2NvcGUsIGFjY291bnQpLFxuICAgIH0pO1xuXG4gICAgcmVwb3NpdG9yeS5ncmFudFB1bGwocHJvamVjdCk7XG5cbiAgICB0aGlzLl9pbWFnZUFjY291bnQgPSBhY2NvdW50O1xuXG4gICAgcmV0dXJuIHtcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHZhbGlkYXRlKGJ1aWxkRW52aXJvbm1lbnQ6IEJ1aWxkRW52aXJvbm1lbnQpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgcmV0ID0gW107XG4gICAgaWYgKGJ1aWxkRW52aXJvbm1lbnQuY29tcHV0ZVR5cGUgJiZcbiAgICAgICAgYnVpbGRFbnZpcm9ubWVudC5jb21wdXRlVHlwZSAhPT0gQ29tcHV0ZVR5cGUuTEFSR0UpIHtcbiAgICAgIHJldC5wdXNoKGBHUFUgaW1hZ2VzIG9ubHkgc3VwcG9ydCBDb21wdXRlVHlwZSAnJHtDb21wdXRlVHlwZS5MQVJHRX0nIC0gYCArXG4gICAgICAgIGAnJHtidWlsZEVudmlyb25tZW50LmNvbXB1dGVUeXBlfScgd2FzIGdpdmVuYCk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBwdWJsaWMgcnVuU2NyaXB0QnVpbGRzcGVjKGVudHJ5cG9pbnQ6IHN0cmluZyk6IEJ1aWxkU3BlYyB7XG4gICAgcmV0dXJuIHJ1blNjcmlwdExpbnV4QnVpbGRTcGVjKGVudHJ5cG9pbnQpO1xuICB9XG59XG4iXX0= |
\ | No newline at end of file |