token-injectable-docker-builder 1.13.3 → 2.0.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/.jsii +260 -143
- package/API.md +196 -136
- package/README.md +156 -71
- package/ecrReplication/ecrReplication.js +156 -0
- package/isComplete/isComplete.js +63 -4
- package/lib/build-spec.d.ts +24 -0
- package/lib/build-spec.js +104 -0
- package/lib/builder.d.ts +206 -0
- package/lib/builder.js +289 -0
- package/lib/constants.d.ts +7 -0
- package/lib/constants.js +11 -0
- package/lib/ecr.d.ts +16 -0
- package/lib/ecr.js +30 -0
- package/lib/index.d.ts +2 -261
- package/lib/index.js +6 -402
- package/lib/provider.d.ts +63 -0
- package/lib/provider.js +212 -0
- package/package.json +10 -5
package/lib/builder.js
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.TokenInjectableDockerBuilder = void 0;
|
|
5
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
+
const crypto = require("crypto");
|
|
7
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
8
|
+
const aws_codebuild_1 = require("aws-cdk-lib/aws-codebuild");
|
|
9
|
+
const aws_ecr_1 = require("aws-cdk-lib/aws-ecr");
|
|
10
|
+
const aws_ecs_1 = require("aws-cdk-lib/aws-ecs");
|
|
11
|
+
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
|
|
12
|
+
const aws_kms_1 = require("aws-cdk-lib/aws-kms");
|
|
13
|
+
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
|
14
|
+
const aws_s3_assets_1 = require("aws-cdk-lib/aws-s3-assets");
|
|
15
|
+
const constructs_1 = require("constructs");
|
|
16
|
+
const build_spec_1 = require("./build-spec");
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
const ecr_1 = require("./ecr");
|
|
19
|
+
const provider_1 = require("./provider");
|
|
20
|
+
/**
|
|
21
|
+
* A CDK construct to build and push Docker images to an ECR repository using
|
|
22
|
+
* CodeBuild and Lambda custom resources, **then** retrieve the final image tag
|
|
23
|
+
* so that ECS/Lambda references use the exact built image.
|
|
24
|
+
*/
|
|
25
|
+
class TokenInjectableDockerBuilder extends constructs_1.Construct {
|
|
26
|
+
constructor(scope, id, props) {
|
|
27
|
+
super(scope, id);
|
|
28
|
+
const { path: sourcePath, buildArgs, dockerLoginSecretArn, vpc, securityGroups, subnetSelection, installCommands, preBuildCommands, kmsEncryption = false, exclude, file: dockerFile, cacheDisabled = false, buildLogGroup, platform = 'linux/amd64', provider, ecrPullThroughCachePrefixes, retainBuildLogs = false, replicaRegions = [], } = props;
|
|
29
|
+
const stack = aws_cdk_lib_1.Stack.of(this);
|
|
30
|
+
this.primaryRegion = stack.region;
|
|
31
|
+
this.accountId = stack.account;
|
|
32
|
+
this.replicaRegions = [...replicaRegions];
|
|
33
|
+
const encryptionKey = kmsEncryption
|
|
34
|
+
? new aws_kms_1.Key(this, 'EcrEncryptionKey', { enableKeyRotation: true })
|
|
35
|
+
: undefined;
|
|
36
|
+
this.ecrRepository = (0, ecr_1.createBuilderEcrRepository)(this, 'ECRRepository', {
|
|
37
|
+
kmsEncryption,
|
|
38
|
+
encryptionKey,
|
|
39
|
+
});
|
|
40
|
+
const dockerFileName = dockerFile ?? 'Dockerfile';
|
|
41
|
+
const effectiveExclude = (0, build_spec_1.resolveExcludes)(sourcePath, dockerFileName, exclude);
|
|
42
|
+
const sourceAsset = new aws_s3_assets_1.Asset(this, 'SourceAsset', {
|
|
43
|
+
path: sourcePath,
|
|
44
|
+
exclude: effectiveExclude,
|
|
45
|
+
});
|
|
46
|
+
// Deterministic image tag: a hash of every input that materially affects
|
|
47
|
+
// the built image. Stable across synths → no spurious rebuilds, and
|
|
48
|
+
// cross-region SSM exports don't churn between deploys (which used to
|
|
49
|
+
// wedge the CDK CrossRegionExportReader/Writer when a deploy was retried
|
|
50
|
+
// after a rollback).
|
|
51
|
+
const imageTag = crypto.createHash('sha256').update(JSON.stringify({
|
|
52
|
+
assetHash: sourceAsset.assetHash,
|
|
53
|
+
dockerFile: dockerFileName,
|
|
54
|
+
buildArgs: buildArgs ?? {},
|
|
55
|
+
platform,
|
|
56
|
+
installCommands: installCommands ?? [],
|
|
57
|
+
preBuildCommands: preBuildCommands ?? [],
|
|
58
|
+
cacheDisabled,
|
|
59
|
+
dockerLoginSecretArn: dockerLoginSecretArn ?? null,
|
|
60
|
+
ecrPullThroughCachePrefixes: ecrPullThroughCachePrefixes ?? [],
|
|
61
|
+
})).digest('hex');
|
|
62
|
+
const buildSpecObj = (0, build_spec_1.buildBuildSpec)({
|
|
63
|
+
imageTag,
|
|
64
|
+
dockerFile,
|
|
65
|
+
buildArgs,
|
|
66
|
+
dockerLoginSecretArn,
|
|
67
|
+
installCommands,
|
|
68
|
+
preBuildCommands,
|
|
69
|
+
cacheDisabled,
|
|
70
|
+
platform,
|
|
71
|
+
});
|
|
72
|
+
const codeBuildImage = platform === 'linux/arm64'
|
|
73
|
+
? aws_codebuild_1.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_3_0
|
|
74
|
+
: aws_codebuild_1.LinuxBuildImage.STANDARD_7_0;
|
|
75
|
+
const codeBuildProject = new aws_codebuild_1.Project(this, 'CodeBuildProject', {
|
|
76
|
+
source: aws_codebuild_1.Source.s3({
|
|
77
|
+
bucket: sourceAsset.bucket,
|
|
78
|
+
path: sourceAsset.s3ObjectKey,
|
|
79
|
+
}),
|
|
80
|
+
environment: {
|
|
81
|
+
buildImage: codeBuildImage,
|
|
82
|
+
privileged: true,
|
|
83
|
+
},
|
|
84
|
+
environmentVariables: {
|
|
85
|
+
ECR_REPO_URI: { value: this.ecrRepository.repositoryUri },
|
|
86
|
+
},
|
|
87
|
+
buildSpec: aws_codebuild_1.BuildSpec.fromObject(buildSpecObj),
|
|
88
|
+
...(buildLogGroup && {
|
|
89
|
+
logging: { cloudWatch: { logGroup: buildLogGroup } },
|
|
90
|
+
}),
|
|
91
|
+
vpc,
|
|
92
|
+
securityGroups,
|
|
93
|
+
subnetSelection,
|
|
94
|
+
});
|
|
95
|
+
this.grantBuildLogsAccess(codeBuildProject, retainBuildLogs);
|
|
96
|
+
this.grantEcrAccess(codeBuildProject);
|
|
97
|
+
this.grantPullThroughCacheAccess(codeBuildProject, ecrPullThroughCachePrefixes);
|
|
98
|
+
if (dockerLoginSecretArn) {
|
|
99
|
+
codeBuildProject.addToRolePolicy(new aws_iam_1.PolicyStatement({
|
|
100
|
+
actions: ['secretsmanager:GetSecretValue'],
|
|
101
|
+
resources: [dockerLoginSecretArn],
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
if (encryptionKey) {
|
|
105
|
+
encryptionKey.grantEncryptDecrypt(codeBuildProject.role);
|
|
106
|
+
}
|
|
107
|
+
const effectiveProvider = provider ?? provider_1.TokenInjectableDockerBuilderProvider.getOrCreate(this);
|
|
108
|
+
effectiveProvider.registerProject(codeBuildProject, this.ecrRepository, encryptionKey);
|
|
109
|
+
if (replicaRegions.length > 0) {
|
|
110
|
+
this.validateReplicaRegions(replicaRegions);
|
|
111
|
+
effectiveProvider.registerReplication(this.ecrRepository.repositoryName, replicaRegions);
|
|
112
|
+
}
|
|
113
|
+
// The CR's construct ID has a "V2" suffix so that a v1-deployed stack
|
|
114
|
+
// upgrading to v2 sees a NEW resource (Replace), not an in-place update
|
|
115
|
+
// of the old `BuildTriggerResource`. CloudFormation forbids modifying a
|
|
116
|
+
// custom resource's `ServiceToken` in-place ("Modifying service token is
|
|
117
|
+
// not allowed."), and the serviceToken changes from v1's per-instance
|
|
118
|
+
// provider to v2's singleton provider. Replace dodges the constraint:
|
|
119
|
+
// the old CR is deleted, and a new one is created with the singleton's
|
|
120
|
+
// serviceToken — at the cost of one fresh build per builder on upgrade.
|
|
121
|
+
const buildTriggerResource = new aws_cdk_lib_1.CustomResource(this, 'BuildTriggerResourceV2', {
|
|
122
|
+
serviceToken: effectiveProvider.serviceToken,
|
|
123
|
+
properties: {
|
|
124
|
+
ProjectName: codeBuildProject.projectName,
|
|
125
|
+
ImageTag: imageTag,
|
|
126
|
+
Trigger: sourceAsset.assetHash,
|
|
127
|
+
RetainBuildLogs: retainBuildLogs ? 'true' : 'false',
|
|
128
|
+
RepositoryName: this.ecrRepository.repositoryName,
|
|
129
|
+
ReplicaRegions: JSON.stringify(replicaRegions),
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
buildTriggerResource.node.addDependency(codeBuildProject);
|
|
133
|
+
// SAFETY: reference by tag, not digest. The lifecycle policy above never
|
|
134
|
+
// deletes tagged images, so the digest behind this tag is guaranteed to
|
|
135
|
+
// remain in ECR for the life of the repository.
|
|
136
|
+
const imageTagRef = buildTriggerResource.getAttString('ImageTag');
|
|
137
|
+
this.imageTag = imageTagRef;
|
|
138
|
+
this.repositoryName = this.ecrRepository.repositoryName;
|
|
139
|
+
this.containerImage = aws_ecs_1.ContainerImage.fromEcrRepository(this.ecrRepository, imageTagRef);
|
|
140
|
+
this.dockerImageCode = aws_lambda_1.DockerImageCode.fromEcr(this.ecrRepository, {
|
|
141
|
+
tagOrDigest: imageTagRef,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Format the ECR repository URI for a given region. The region must
|
|
146
|
+
* be either the primary region or one of `replicaRegions`.
|
|
147
|
+
*/
|
|
148
|
+
repositoryUriFor(region) {
|
|
149
|
+
this.assertRegionIsKnown(region);
|
|
150
|
+
return `${this.accountId}.dkr.ecr.${region}.amazonaws.com/${this.repositoryName}`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Import the replicated repository as an ECS-compatible
|
|
154
|
+
* `ContainerImage` in a consumer scope (typically a stack in `region`).
|
|
155
|
+
*
|
|
156
|
+
* The consumer's stack must have `crossRegionReferences: true` when
|
|
157
|
+
* `region` differs from the builder's region.
|
|
158
|
+
*/
|
|
159
|
+
containerImageFor(scope, region) {
|
|
160
|
+
return aws_ecs_1.ContainerImage.fromEcrRepository(this.importRepoFor(scope, region), this.imageTag);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Import the replicated repository as a Lambda-compatible
|
|
164
|
+
* `DockerImageCode` in a consumer scope (typically a stack in `region`).
|
|
165
|
+
*
|
|
166
|
+
* The consumer's stack must have `crossRegionReferences: true` when
|
|
167
|
+
* `region` differs from the builder's region.
|
|
168
|
+
*/
|
|
169
|
+
dockerImageCodeFor(scope, region) {
|
|
170
|
+
return aws_lambda_1.DockerImageCode.fromEcr(this.importRepoFor(scope, region), {
|
|
171
|
+
tagOrDigest: this.imageTag,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
importRepoFor(scope, region) {
|
|
175
|
+
this.assertRegionIsKnown(region);
|
|
176
|
+
if (region === this.primaryRegion)
|
|
177
|
+
return this.ecrRepository;
|
|
178
|
+
// Include the builder's own node.addr in the import id so two different
|
|
179
|
+
// builders importing the same region into the same scope each get their
|
|
180
|
+
// own Repository child (otherwise the second call would collide with the
|
|
181
|
+
// first and return the wrong builder's repo).
|
|
182
|
+
const importId = `ImportedRepo${region}${this.node.addr}`;
|
|
183
|
+
const existing = scope.node.tryFindChild(importId);
|
|
184
|
+
if (existing)
|
|
185
|
+
return existing;
|
|
186
|
+
return aws_ecr_1.Repository.fromRepositoryAttributes(scope, importId, {
|
|
187
|
+
repositoryName: this.repositoryName,
|
|
188
|
+
repositoryArn: aws_cdk_lib_1.Stack.of(scope).formatArn({
|
|
189
|
+
service: 'ecr',
|
|
190
|
+
resource: 'repository',
|
|
191
|
+
resourceName: this.repositoryName,
|
|
192
|
+
region,
|
|
193
|
+
account: this.accountId,
|
|
194
|
+
}),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
assertRegionIsKnown(region) {
|
|
198
|
+
if (region === this.primaryRegion)
|
|
199
|
+
return;
|
|
200
|
+
if (this.replicaRegions.includes(region))
|
|
201
|
+
return;
|
|
202
|
+
throw new Error(`Region "${region}" is not the primary region (${this.primaryRegion}) ` +
|
|
203
|
+
`or one of the configured replicaRegions (${this.replicaRegions.join(', ') || '<none>'}). ` +
|
|
204
|
+
'Add the region to the builder\'s replicaRegions prop to make it available.');
|
|
205
|
+
}
|
|
206
|
+
validateReplicaRegions(replicaRegions) {
|
|
207
|
+
const stack = aws_cdk_lib_1.Stack.of(this);
|
|
208
|
+
const primaryPartition = stack.partition;
|
|
209
|
+
for (const region of replicaRegions) {
|
|
210
|
+
if (region === this.primaryRegion) {
|
|
211
|
+
throw new Error(`replicaRegions cannot include the primary region "${this.primaryRegion}". ` +
|
|
212
|
+
'Remove it from the list.');
|
|
213
|
+
}
|
|
214
|
+
// Partition cannot be cleanly inferred from region alone at synth time
|
|
215
|
+
// (it's a CDK pseudo-parameter and may be a token). We do the best-effort
|
|
216
|
+
// check: if both partition values are concrete and they differ, fail.
|
|
217
|
+
// Cross-partition replication is unsupported by ECR.
|
|
218
|
+
if (!aws_cdk_lib_1.Token.isUnresolved(primaryPartition)) {
|
|
219
|
+
const expectedPartition = inferPartition(region);
|
|
220
|
+
if (expectedPartition && expectedPartition !== primaryPartition) {
|
|
221
|
+
throw new Error('Cross-partition ECR replication is not supported. ' +
|
|
222
|
+
`Primary partition is "${primaryPartition}" but replica region ` +
|
|
223
|
+
`"${region}" appears to be in partition "${expectedPartition}".`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
grantEcrAccess(project) {
|
|
229
|
+
this.ecrRepository.grantPullPush(project);
|
|
230
|
+
project.addToRolePolicy(new aws_iam_1.PolicyStatement({
|
|
231
|
+
actions: [
|
|
232
|
+
'ecr:GetAuthorizationToken',
|
|
233
|
+
'ecr:GetDownloadUrlForLayer',
|
|
234
|
+
'ecr:BatchCheckLayerAvailability',
|
|
235
|
+
'ecr:BatchGetImage',
|
|
236
|
+
],
|
|
237
|
+
resources: ['*'],
|
|
238
|
+
}));
|
|
239
|
+
}
|
|
240
|
+
grantPullThroughCacheAccess(project, prefixes) {
|
|
241
|
+
if (!prefixes || prefixes.length === 0)
|
|
242
|
+
return;
|
|
243
|
+
const stack = aws_cdk_lib_1.Stack.of(this);
|
|
244
|
+
project.addToRolePolicy(new aws_iam_1.PolicyStatement({
|
|
245
|
+
actions: [
|
|
246
|
+
'ecr:BatchGetImage',
|
|
247
|
+
'ecr:GetDownloadUrlForLayer',
|
|
248
|
+
'ecr:BatchCheckLayerAvailability',
|
|
249
|
+
'ecr:BatchImportUpstreamImage',
|
|
250
|
+
'ecr:CreateRepository',
|
|
251
|
+
],
|
|
252
|
+
resources: prefixes.map((prefix) => `arn:aws:ecr:${stack.region}:${stack.account}:repository/${prefix}/*`),
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
grantBuildLogsAccess(project, retainBuildLogs) {
|
|
256
|
+
if (!retainBuildLogs)
|
|
257
|
+
return;
|
|
258
|
+
const stack = aws_cdk_lib_1.Stack.of(this);
|
|
259
|
+
project.addToRolePolicy(new aws_iam_1.PolicyStatement({
|
|
260
|
+
actions: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
|
|
261
|
+
resources: [
|
|
262
|
+
`arn:aws:logs:${stack.region}:${stack.account}:log-group:${constants_1.BUILD_LOG_GROUP_PREFIX}${project.projectName}`,
|
|
263
|
+
`arn:aws:logs:${stack.region}:${stack.account}:log-group:${constants_1.BUILD_LOG_GROUP_PREFIX}${project.projectName}:*`,
|
|
264
|
+
],
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
exports.TokenInjectableDockerBuilder = TokenInjectableDockerBuilder;
|
|
269
|
+
_a = JSII_RTTI_SYMBOL_1;
|
|
270
|
+
TokenInjectableDockerBuilder[_a] = { fqn: "token-injectable-docker-builder.TokenInjectableDockerBuilder", version: "2.0.0" };
|
|
271
|
+
/**
|
|
272
|
+
* Best-effort partition inference from an AWS region name. Returns
|
|
273
|
+
* undefined if the region doesn't look like a known partition prefix —
|
|
274
|
+
* callers should treat that as "skip the partition check".
|
|
275
|
+
*/
|
|
276
|
+
function inferPartition(region) {
|
|
277
|
+
if (region.startsWith('cn-'))
|
|
278
|
+
return 'aws-cn';
|
|
279
|
+
if (region.startsWith('us-gov-'))
|
|
280
|
+
return 'aws-us-gov';
|
|
281
|
+
if (region.startsWith('us-iso-'))
|
|
282
|
+
return 'aws-iso';
|
|
283
|
+
if (region.startsWith('us-isob-'))
|
|
284
|
+
return 'aws-iso-b';
|
|
285
|
+
if (/^[a-z]{2}-[a-z]+-\d+$/.test(region))
|
|
286
|
+
return 'aws';
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaUNBQWlDO0FBRWpDLDZDQUEyRDtBQUMzRCw2REFNbUM7QUFFbkMsaURBQWlEO0FBQ2pELGlEQUFxRDtBQUNyRCxpREFBc0Q7QUFDdEQsaURBQTBDO0FBQzFDLHVEQUF5RDtBQUV6RCw2REFBa0Q7QUFDbEQsMkNBQXVDO0FBRXZDLDZDQUErRDtBQUMvRCwyQ0FBcUQ7QUFDckQsK0JBQW1EO0FBQ25ELHlDQUFrRTtBQTBLbEU7Ozs7R0FJRztBQUNILE1BQWEsNEJBQTZCLFNBQVEsc0JBQVM7SUFvQnpELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBd0M7UUFDaEYsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixNQUFNLEVBQ0osSUFBSSxFQUFFLFVBQVUsRUFDaEIsU0FBUyxFQUNULG9CQUFvQixFQUNwQixHQUFHLEVBQ0gsY0FBYyxFQUNkLGVBQWUsRUFDZixlQUFlLEVBQ2YsZ0JBQWdCLEVBQ2hCLGFBQWEsR0FBRyxLQUFLLEVBQ3JCLE9BQU8sRUFDUCxJQUFJLEVBQUUsVUFBVSxFQUNoQixhQUFhLEdBQUcsS0FBSyxFQUNyQixhQUFhLEVBQ2IsUUFBUSxHQUFHLGFBQWEsRUFDeEIsUUFBUSxFQUNSLDJCQUEyQixFQUMzQixlQUFlLEdBQUcsS0FBSyxFQUN2QixjQUFjLEdBQUcsRUFBRSxHQUNwQixHQUFHLEtBQUssQ0FBQztRQUVWLE1BQU0sS0FBSyxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUNsQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFDL0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxDQUFDLEdBQUcsY0FBYyxD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QUFDO1lBQ2xCLE9BQU8sRUFBRSxDQUFDLHFCQUFxQixFQUFFLHNCQUFzQixFQUFFLG1CQUFtQixDQUFDO1lBQzdFLFNBQVMsRUFBRTtnQkFDVCxnQkFBZ0IsS0FBSyxDQUFDLE1BQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxjQUFjLGtDQUFzQixHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUU7Z0JBQ3pHLGdCQUFnQixLQUFLLENBQUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLGNBQWMsa0NBQXNCLEdBQUcsT0FBTyxDQUFDLFdBQVcsSUFBSTthQUM1RztTQUNGLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQzs7QUFoVUgsb0VBaVVDOzs7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxjQUFjLENBQUMsTUFBYztJQUNwQyxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDOUMsSUFBSSxNQUFNLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQztRQUFFLE9BQU8sWUFBWSxDQUFDO0lBQ3RELElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUNuRCxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1FBQUUsT0FBTyxXQUFXLENBQUM7SUFDdEQsSUFBSSx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDdkQsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdjcnlwdG8nO1xuXG5pbXBvcnQgeyBDdXN0b21SZXNvdXJjZSwgU3RhY2ssIFRva2VuIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgUHJvamVjdCxcbiAgU291cmNlLFxuICBMaW51eEJ1aWxkSW1hZ2UsXG4gIExpbnV4QXJtQnVpbGRJbWFnZSxcbiAgQnVpbGRTcGVjLFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY29kZWJ1aWxkJztcbmltcG9ydCB7IElWcGMsIElTZWN1cml0eUdyb3VwLCBTdWJuZXRTZWxlY3Rpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCB7IFJlcG9zaXRvcnkgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWNyJztcbmltcG9ydCB7IENvbnRhaW5lckltYWdlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjcyc7XG5pbXBvcnQgeyBQb2xpY3lTdGF0ZW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IEtleSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1rbXMnO1xuaW1wb3J0IHsgRG9ja2VySW1hZ2VDb2RlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBJTG9nR3JvdXAgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQgeyBBc3NldCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMy1hc3NldHMnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5cbmltcG9ydCB7IGJ1aWxkQnVpbGRTcGVjLCByZXNvbHZlRXhjbHVkZXMgfSBmcm9tICcuL2J1aWxkLXNwZWMnO1xuaW1wb3J0IHsgQlVJTERfTE9HX0dST1VQX1BSRUZJWCB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IGNyZWF0ZUJ1aWxkZXJFY3JSZXBvc2l0b3J5IH0gZnJvbSAnLi9lY3InO1xuaW1wb3J0IHsgVG9rZW5JbmplY3RhYmxlRG9ja2VyQnVpbGRlclByb3ZpZGVyIH0gZnJvbSAnLi9wcm92aWRlcic7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgdGhlIGBUb2tlbkluamVjdGFibGVEb2NrZXJCdWlsZGVyYCBjb25zdHJ1Y3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVG9rZW5JbmplY3RhYmxlRG9ja2VyQnVpbGRlclByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBwYXRoIHRvIHRoZSBkaXJlY3RvcnkgY29udGFpbmluZyB0aGUgRG9ja2VyZmlsZSBvciBzb3VyY2UgY29kZS5cbiAgICovXG4gIHJlYWRvbmx5IHBhdGg6IHN0cmluZztcblxuICAvKipcbiAgICogQnVpbGQgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIERvY2tlciBidWlsZCBwcm9jZXNzLlxuICAgKiBUaGVzZSBhcmUgdHJhbnNmb3JtZWQgaW50byBgLS1idWlsZC1hcmcgS0VZPVZBTFVFYCBmbGFncy5cbiAgICogQGV4YW1wbGVcbiAgICoge1xuICAgKiAgIFRPS0VOOiAnbXktc2VjcmV0LXRva2VuJyxcbiAgICogICBFTlY6ICdwcm9kdWN0aW9uJ1xuICAgKiB9XG4gICAqL1xuICByZWFkb25seSBidWlsZEFyZ3M/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBUaGUgQVJOIG9mIHRoZSBBV1MgU2VjcmV0cyBNYW5hZ2VyIHNlY3JldCBjb250YWluaW5nIERvY2tlciBsb2dpbiBjcmVkZW50aWFscy5cbiAgICogVGhlIHNlY3JldCBtdXN0IHN0b3JlIGEgSlNPTiBvYmplY3Q6IGB7XCJ1c2VybmFtZVwiOlwiLi4uXCIsXCJwYXNzd29yZFwiOlwiLi4uXCJ9YC5cbiAgICogTXVzdCBiZSBpbiB0aGUgc2FtZSByZWdpb24gYXMgdGhlIHN0YWNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIERvY2tlciBIdWIgbG9naW4uXG4gICAqL1xuICByZWFkb25seSBkb2NrZXJMb2dpblNlY3JldEFybj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIFZQQyBpbiB3aGljaCB0aGUgQ29kZUJ1aWxkIHByb2plY3Qgd2lsbCBiZSBkZXBsb3llZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBDb2RlQnVpbGQgdXNlcyBwdWJsaWMgaW50ZXJuZXQuXG4gICAqL1xuICByZWFkb25seSB2cGM/OiBJVnBjO1xuXG4gIC8qKlxuICAgKiBTZWN1cml0eSBncm91cHMgYXR0YWNoZWQgdG8gdGhlIENvZGVCdWlsZCBwcm9qZWN0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHNlY3VyaXR5IGdyb3VwcyBhdHRhY2hlZC5cbiAgICovXG4gIHJlYWRvbmx5IHNlY3VyaXR5R3JvdXBzPzogSVNlY3VyaXR5R3JvdXBbXTtcblxuICAvKipcbiAgICogU3VibmV0IHNlbGVjdGlvbiB3aXRoaW4gdGhlIFZQQy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBbGwgc3VibmV0cyBpbiB0aGUgVlBDLlxuICAgKi9cbiAgcmVhZG9ubHkgc3VibmV0U2VsZWN0aW9uPzogU3VibmV0U2VsZWN0aW9uO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gY29tbWFuZHMgdG8gcnVuIGR1cmluZyB0aGUgaW5zdGFsbCBwaGFzZSBvZiBDb2RlQnVpbGQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gYWRkaXRpb25hbCBpbnN0YWxsIGNvbW1hbmRzLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5zdGFsbENvbW1hbmRzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBjb21tYW5kcyB0byBydW4gZHVyaW5nIHRoZSBwcmVfYnVpbGQgcGhhc2Ugb2YgQ29kZUJ1aWxkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGFkZGl0aW9uYWwgcHJlLWJ1aWxkIGNvbW1hbmRzLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJlQnVpbGRDb21tYW5kcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGVuYWJsZSBLTVMgZW5jcnlwdGlvbiBmb3IgdGhlIEVDUiByZXBvc2l0b3J5LlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkga21zRW5jcnlwdGlvbj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEZpbGUgcGF0aHMgaW4gdGhlIERvY2tlciBkaXJlY3RvcnkgdG8gZXhjbHVkZSBmcm9tIHRoZSBidWlsZCBhc3NldC5cbiAgICogRmFsbHMgYmFjayB0byBgLmRvY2tlcmlnbm9yZWAgaWYgcHJlc2VudC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBmaWxlIHBhdGggZXhjbHVzaW9ucy5cbiAgICovXG4gIHJlYWRvbmx5IGV4Y2x1ZGU/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgRG9ja2VyZmlsZSAocGFzc2VkIGFzIGAtZmApLlxuICAgKlxuICAgKiBAZXhhbXBsZSAnRG9ja2VyZmlsZS5wcm9kdWN0aW9uJ1xuICAgKiBAZGVmYXVsdCAnRG9ja2VyZmlsZSdcbiAgICovXG4gIHJlYWRvbmx5IGZpbGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZW4gYHRydWVgLCBkaXNhYmxlcyBEb2NrZXIgbGF5ZXIgY2FjaGluZy5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGNhY2hlRGlzYWJsZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDbG91ZFdhdGNoIGxvZyBncm91cCBmb3IgQ29kZUJ1aWxkIGJ1aWxkIGxvZ3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQ29kZUJ1aWxkIGRlZmF1bHQgbG9nZ2luZy5cbiAgICovXG4gIHJlYWRvbmx5IGJ1aWxkTG9nR3JvdXA/OiBJTG9nR3JvdXA7XG5cbiAgLyoqXG4gICAqIFRhcmdldCBwbGF0Zm9ybSBmb3IgdGhlIERvY2tlciBpbWFnZS5cbiAgICpcbiAgICogQGRlZmF1bHQgJ2xpbnV4L2FtZDY0J1xuICAgKi9cbiAgcmVhZG9ubHkgcGxhdGZvcm0/OiAnbGludXgvYW1kNjQnIHwgJ2xpbnV4L2FybTY0JztcblxuICAvKipcbiAgICogU2hhcmVkIHByb3ZpZGVyIGZvciB0aGUgY3VzdG9tIHJlc291cmNlIExhbWJkYXMuXG4gICAqXG4gICAqIFBhc3MgYFRva2VuSW5qZWN0YWJsZURvY2tlckJ1aWxkZXJQcm92aWRlci5nZXRPckNyZWF0ZSh0aGlzLCB7IHF1ZXJ5SW50ZXJ2YWwgfSlgXG4gICAqIGlmIHlvdSBuZWVkIGEgbm9uLWRlZmF1bHQgcXVlcnkgaW50ZXJ2YWwuIE90aGVyd2lzZSwgdGhlIGNvbnN0cnVjdCB3aWxsXG4gICAqIGNhbGwgYGdldE9yQ3JlYXRlKHRoaXMpYCBpdHNlbGYgYW5kIHJldXNlIHRoZSBwZXItc3RhY2sgc2luZ2xldG9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFBlci1zdGFjayBzaW5nbGV0b24gcHJvdmlkZXIsIGNyZWF0ZWQgb24gZmlyc3QgdXNlLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvdmlkZXI/OiBUb2tlbkluamVjdGFibGVEb2NrZXJCdWlsZGVyUHJvdmlkZXI7XG5cbiAgLyoqXG4gICAqIEVDUiBwdWxsLXRocm91Z2ggY2FjaGUgcmVwb3NpdG9yeSBwcmVmaXhlcyB0byBncmFudCBwdWxsIGFjY2VzcyB0by5cbiAgICpcbiAgICogQGV4YW1wbGUgWydkb2NrZXItaHViJywgJ2doY3InXVxuICAgKiBAZGVmYXVsdCAtIE5vIHB1bGwtdGhyb3VnaCBjYWNoZSBhY2Nlc3MuXG4gICAqL1xuICByZWFkb25seSBlY3JQdWxsVGhyb3VnaENhY2hlUHJlZml4ZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogV2hlbiBgdHJ1ZWAsIGNyZWF0ZXMgYSBDbG91ZFdhdGNoIGxvZyBncm91cCBvdXRzaWRlIG9mIENsb3VkRm9ybWF0aW9uXG4gICAqIChgL2RvY2tlci1idWlsZGVyLzxwcm9qZWN0TmFtZT5gKSBhbmQgZGlyZWN0cyBDb2RlQnVpbGQgb3V0cHV0IHRoZXJlLlxuICAgKiBTdXJ2aXZlcyBzdGFjayByb2xsYmFja3MgZm9yIGRlYnVnZ2luZy4gNy1kYXkgcmV0ZW50aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgcmV0YWluQnVpbGRMb2dzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBBV1MgcmVnaW9ucyB0byByZXBsaWNhdGUgdGhlIGJ1aWx0IGltYWdlIHRvIHZpYSBFQ1Inc1xuICAgKiBuYXRpdmUgcmVnaXN0cnkgcmVwbGljYXRpb24uIFRoZSBpbWFnZSBpcyBwdXNoZWQgdG8gdGhlIHByaW1hcnlcbiAgICogcmVnaW9uJ3MgRUNSIGFzIHVzdWFsOyBFQ1IgYXN5bmNocm9ub3VzbHkgcmVwbGljYXRlcyB0aGUgc2FtZVxuICAgKiBgcmVwb3NpdG9yeU5hbWVgICsgYGltYWdlVGFnYCB0byBlYWNoIHJlZ2lvbiBsaXN0ZWQgaGVyZS5cbiAgICpcbiAgICogQ29uc3VtZXJzIGluIGFub3RoZXIgcmVnaW9uIChhIExhbWJkYSBpbiBgdXMtd2VzdC0yYCByZWZlcmVuY2luZyBhblxuICAgKiBpbWFnZSBidWlsdCBpbiBgdXMtZWFzdC0xYCkgY2FuIHVzZSBgZG9ja2VySW1hZ2VDb2RlRm9yKHJlZ2lvbilgIG9yXG4gICAqIGBjb250YWluZXJJbWFnZUZvcihyZWdpb24pYCB0byBpbXBvcnQgdGhlIHJlcGxpY2F0ZWQgaW1hZ2UuXG4gICAqXG4gICAqIFRoZSBjdXN0b20gcmVzb3VyY2Ugd2FpdHMgZm9yIHJlcGxpY2F0aW9uIHRvIGNvbXBsZXRlIGJlZm9yZVxuICAgKiBzaWduYWxsaW5nIGRlcGxveS1jb21wbGV0ZSwgc28gZG93bnN0cmVhbSBzdGFja3MgY2FuIHNhZmVseSBkZXBsb3lcbiAgICogaW1tZWRpYXRlbHkgYWZ0ZXIuXG4gICAqXG4gICAqICoqQ2F2ZWF0czoqKlxuICAgKiAtIENyb3NzLXJlZ2lvbiByZXBsaWNhdGlvbiBpcyBub3Qgc3VwcG9ydGVkIGJldHdlZW4gQVdTIHBhcnRpdGlvbnMuXG4gICAqIC0gUmVwbGljYXMgZG8gKipub3QqKiBpbmhlcml0IHRoZSBwcmltYXJ5J3MgZW5jcnlwdGlvbiAoZGVmYXVsdHMgdG9cbiAgICogICBBRVMtMjU2KSwgbGlmZWN5Y2xlIHBvbGljaWVzLCBvciByZXBvc2l0b3J5IHBvbGljaWVzLlxuICAgKiAtIFJlcGxpY2F0ZWQgcmVwb3NpdG9yaWVzIHBlcnNpc3Qgb24gc3RhY2sgZGVsZXRpb24g4oCUIEFXUyBkb2VzIG5vdFxuICAgKiAgIGF1dG8tZGVsZXRlIHRoZW0uIENsZWFuIHVwIG1hbnVhbGx5IHZpYSB0aGUgRUNSIGNvbnNvbGUgLyBDTEkgaWZcbiAgICogICBuZWVkZWQuXG4gICAqIC0gQm90aCB0aGUgYnVpbGRlciBzdGFjayBhbmQgYW55IGNvbnN1bWVyIHN0YWNrIGluIGFub3RoZXIgcmVnaW9uXG4gICAqICAgbXVzdCBzZXQgYGNyb3NzUmVnaW9uUmVmZXJlbmNlczogdHJ1ZWAgZm9yIHRoZSBpbWFnZSB0YWcgdG8gZmxvdy5cbiAgICogLSBTdGFja3MgbXVzdCBoYXZlIGEgY29uY3JldGUgcmVnaW9uIChgZW52OiB7IGFjY291bnQsIHJlZ2lvbiB9YCksXG4gICAqICAgbm90IHRoZSBlbnYtYWdub3N0aWMgZGVmYXVsdC5cbiAgICpcbiAgICogQGV4YW1wbGUgWyd1cy13ZXN0LTInLCAnZXUtd2VzdC0xJ11cbiAgICogQGRlZmF1bHQgW10gLSBubyByZXBsaWNhdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgcmVwbGljYVJlZ2lvbnM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBBIENESyBjb25zdHJ1Y3QgdG8gYnVpbGQgYW5kIHB1c2ggRG9ja2VyIGltYWdlcyB0byBhbiBFQ1IgcmVwb3NpdG9yeSB1c2luZ1xuICogQ29kZUJ1aWxkIGFuZCBMYW1iZGEgY3VzdG9tIHJlc291cmNlcywgKip0aGVuKiogcmV0cmlldmUgdGhlIGZpbmFsIGltYWdlIHRhZ1xuICogc28gdGhhdCBFQ1MvTGFtYmRhIHJlZmVyZW5jZXMgdXNlIHRoZSBleGFjdCBidWlsdCBpbWFnZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFRva2VuSW5qZWN0YWJsZURvY2tlckJ1aWxkZXIgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKiogVGhlIEVDUiByZXBvc2l0b3J5IHRoYXQgc3RvcmVzIHRoZSByZXN1bHRpbmcgRG9ja2VyIGltYWdlLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGVjclJlcG9zaXRvcnk6IFJlcG9zaXRvcnk7XG5cbiAgLyoqIEVDUy1jb21wYXRpYmxlIGNvbnRhaW5lciBpbWFnZSByZWZlcmVuY2UgKHByaW1hcnkgcmVnaW9uKS4gKi9cbiAgcHVibGljIHJlYWRvbmx5IGNvbnRhaW5lckltYWdlOiBDb250YWluZXJJbWFnZTtcblxuICAvKiogTGFtYmRhLWNvbXBhdGlibGUgRG9ja2VySW1hZ2VDb2RlIHJlZmVyZW5jZSAocHJpbWFyeSByZWdpb24pLiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZG9ja2VySW1hZ2VDb2RlOiBEb2NrZXJJbWFnZUNvZGU7XG5cbiAgLyoqIFRoZSBFQ1IgcmVwb3NpdG9yeSBuYW1lIOKAlCBwcmVzZXJ2ZWQgYWNyb3NzIHJlcGxpY2EgcmVnaW9ucy4gKi9cbiAgcHVibGljIHJlYWRvbmx5IHJlcG9zaXRvcnlOYW1lOiBzdHJpbmc7XG5cbiAgLyoqIFRoZSByZXNvbHZlZCBpbWFnZSB0YWcgKENGTiB0b2tlbjsgYXZhaWxhYmxlIGF0IGRlcGxveSB0aW1lKS4gKi9cbiAgcHVibGljIHJlYWRvbmx5IGltYWdlVGFnOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwcmltYXJ5UmVnaW9uOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgYWNjb3VudElkOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVwbGljYVJlZ2lvbnM6IHN0cmluZ1tdO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBUb2tlbkluamVjdGFibGVEb2NrZXJCdWlsZGVyUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3Qge1xuICAgICAgcGF0aDogc291cmNlUGF0aCxcbiAgICAgIGJ1aWxkQXJncyxcbiAgICAgIGRvY2tlckxvZ2luU2VjcmV0QXJuLFxuICAgICAgdnBjLFxuICAgICAgc2VjdXJpdHlHcm91cHMsXG4gICAgICBzdWJuZXRTZWxlY3Rpb24sXG4gICAgICBpbnN0YWxsQ29tbWFuZHMsXG4gICAgICBwcmVCdWlsZENvbW1hbmRzLFxuICAgICAga21zRW5jcnlwdGlvbiA9IGZhbHNlLFxuICAgICAgZXhjbHVkZSxcbiAgICAgIGZpbGU6IGRvY2tlckZpbGUsXG4gICAgICBjYWNoZURpc2FibGVkID0gZmFsc2UsXG4gICAgICBidWlsZExvZ0dyb3VwLFxuICAgICAgcGxhdGZvcm0gPSAnbGludXgvYW1kNjQnLFxuICAgICAgcHJvdmlkZXIsXG4gICAgICBlY3JQdWxsVGhyb3VnaENhY2hlUHJlZml4ZXMsXG4gICAgICByZXRhaW5CdWlsZExvZ3MgPSBmYWxzZSxcbiAgICAgIHJlcGxpY2FSZWdpb25zID0gW10sXG4gICAgfSA9IHByb3BzO1xuXG4gICAgY29uc3Qgc3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICB0aGlzLnByaW1hcnlSZWdpb24gPSBzdGFjay5yZWdpb247XG4gICAgdGhpcy5hY2NvdW50SWQgPSBzdGFjay5hY2NvdW50O1xuICAgIHRoaXMucmVwbGljYVJlZ2lvbnMgPSBbLi4ucmVwbGljYVJlZ2lvbnNdO1xuXG4gICAgY29uc3QgZW5jcnlwdGlvbktleSA9IGttc0VuY3J5cHRpb25cbiAgICAgID8gbmV3IEtleSh0aGlzLCAnRWNyRW5jcnlwdGlvbktleScsIHsgZW5hYmxlS2V5Um90YXRpb246IHRydWUgfSlcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgdGhpcy5lY3JSZXBvc2l0b3J5ID0gY3JlYXRlQnVpbGRlckVjclJlcG9zaXRvcnkodGhpcywgJ0VDUlJlcG9zaXRvcnknLCB7XG4gICAgICBrbXNFbmNyeXB0aW9uLFxuICAgICAgZW5jcnlwdGlvbktleSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGRvY2tlckZpbGVOYW1lID0gZG9ja2VyRmlsZSA/PyAnRG9ja2VyZmlsZSc7XG4gICAgY29uc3QgZWZmZWN0aXZlRXhjbHVkZSA9IHJlc29sdmVFeGNsdWRlcyhzb3VyY2VQYXRoLCBkb2NrZXJGaWxlTmFtZSwgZXhjbHVkZSk7XG5cbiAgICBjb25zdCBzb3VyY2VBc3NldCA9IG5ldyBBc3NldCh0aGlzLCAnU291cmNlQXNzZXQnLCB7XG4gICAgICBwYXRoOiBzb3VyY2VQYXRoLFxuICAgICAgZXhjbHVkZTogZWZmZWN0aXZlRXhjbHVkZSxcbiAgICB9KTtcblxuICAgIC8vIERldGVybWluaXN0aWMgaW1hZ2UgdGFnOiBhIGhhc2ggb2YgZXZlcnkgaW5wdXQgdGhhdCBtYXRlcmlhbGx5IGFmZmVjdHNcbiAgICAvLyB0aGUgYnVpbHQgaW1hZ2UuIFN0YWJsZSBhY3Jvc3Mgc3ludGhzIOKGkiBubyBzcHVyaW91cyByZWJ1aWxkcywgYW5kXG4gICAgLy8gY3Jvc3MtcmVnaW9uIFNTTSBleHBvcnRzIGRvbid0IGNodXJuIGJldHdlZW4gZGVwbG95cyAod2hpY2ggdXNlZCB0b1xuICAgIC8vIHdlZGdlIHRoZSBDREsgQ3Jvc3NSZWdpb25FeHBvcnRSZWFkZXIvV3JpdGVyIHdoZW4gYSBkZXBsb3kgd2FzIHJldHJpZWRcbiAgICAvLyBhZnRlciBhIHJvbGxiYWNrKS5cbiAgICBjb25zdCBpbWFnZVRhZyA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgYXNzZXRIYXNoOiBzb3VyY2VBc3NldC5hc3NldEhhc2gsXG4gICAgICBkb2NrZXJGaWxlOiBkb2NrZXJGaWxlTmFtZSxcbiAgICAgIGJ1aWxkQXJnczogYnVpbGRBcmdzID8/IHt9LFxuICAgICAgcGxhdGZvcm0sXG4gICAgICBpbnN0YWxsQ29tbWFuZHM6IGluc3RhbGxDb21tYW5kcyA/PyBbXSxcbiAgICAgIHByZUJ1aWxkQ29tbWFuZHM6IHByZUJ1aWxkQ29tbWFuZHMgPz8gW10sXG4gICAgICBjYWNoZURpc2FibGVkLFxuICAgICAgZG9ja2VyTG9naW5TZWNyZXRBcm46IGRvY2tlckxvZ2luU2VjcmV0QXJuID8/IG51bGwsXG4gICAgICBlY3JQdWxsVGhyb3VnaENhY2hlUHJlZml4ZXM6IGVjclB1bGxUaHJvdWdoQ2FjaGVQcmVmaXhlcyA/PyBbXSxcbiAgICB9KSkuZGlnZXN0KCdoZXgnKTtcblxuICAgIGNvbnN0IGJ1aWxkU3BlY09iaiA9IGJ1aWxkQnVpbGRTcGVjKHtcbiAgICAgIGltYWdlVGFnLFxuICAgICAgZG9ja2VyRmlsZSxcbiAgICAgIGJ1aWxkQXJncyxcbiAgICAgIGRvY2tlckxvZ2luU2VjcmV0QXJuLFxuICAgICAgaW5zdGFsbENvbW1hbmRzLFxuICAgICAgcHJlQnVpbGRDb21tYW5kcyxcbiAgICAgIGNhY2hlRGlzYWJsZWQsXG4gICAgICBwbGF0Zm9ybSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGNvZGVCdWlsZEltYWdlID0gcGxhdGZvcm0gPT09ICdsaW51eC9hcm02NCdcbiAgICAgID8gTGludXhBcm1CdWlsZEltYWdlLkFNQVpPTl9MSU5VWF8yX1NUQU5EQVJEXzNfMFxuICAgICAgOiBMaW51eEJ1aWxkSW1hZ2UuU1RBTkRBUkRfN18wO1xuXG4gICAgY29uc3QgY29kZUJ1aWxkUHJvamVjdCA9IG5ldyBQcm9qZWN0KHRoaXMsICdDb2RlQnVpbGRQcm9qZWN0Jywge1xuICAgICAgc291cmNlOiBTb3VyY2UuczMoe1xuICAgICAgICBidWNrZXQ6IHNvdXJjZUFzc2V0LmJ1Y2tldCxcbiAgICAgICAgcGF0aDogc291cmNlQXNzZXQuczNPYmplY3RLZXksXG4gICAgICB9KSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIGJ1aWxkSW1hZ2U6IGNvZGVCdWlsZEltYWdlLFxuICAgICAgICBwcml2aWxlZ2VkOiB0cnVlLFxuICAgICAgfSxcbiAgICAgIGVudmlyb25tZW50VmFyaWFibGVzOiB7XG4gICAgICAgIEVDUl9SRVBPX1VSSTogeyB2YWx1ZTogdGhpcy5lY3JSZXBvc2l0b3J5LnJlcG9zaXRvcnlVcmkgfSxcbiAgICAgIH0sXG4gICAgICBidWlsZFNwZWM6IEJ1aWxkU3BlYy5mcm9tT2JqZWN0KGJ1aWxkU3BlY09iaiksXG4gICAgICAuLi4oYnVpbGRMb2dHcm91cCAmJiB7XG4gICAgICAgIGxvZ2dpbmc6IHsgY2xvdWRXYXRjaDogeyBsb2dHcm91cDogYnVpbGRMb2dHcm91cCB9IH0sXG4gICAgICB9KSxcbiAgICAgIHZwYyxcbiAgICAgIHNlY3VyaXR5R3JvdXBzLFxuICAgICAgc3VibmV0U2VsZWN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5ncmFudEJ1aWxkTG9nc0FjY2Vzcyhjb2RlQnVpbGRQcm9qZWN0LCByZXRhaW5CdWlsZExvZ3MpO1xuICAgIHRoaXMuZ3JhbnRFY3JBY2Nlc3MoY29kZUJ1aWxkUHJvamVjdCk7XG4gICAgdGhpcy5ncmFudFB1bGxUaHJvdWdoQ2FjaGVBY2Nlc3MoY29kZUJ1aWxkUHJvamVjdCwgZWNyUHVsbFRocm91Z2hDYWNoZVByZWZpeGVzKTtcblxuICAgIGlmIChkb2NrZXJMb2dpblNlY3JldEFybikge1xuICAgICAgY29kZUJ1aWxkUHJvamVjdC5hZGRUb1JvbGVQb2xpY3koXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFsnc2VjcmV0c21hbmFnZXI6R2V0U2VjcmV0VmFsdWUnXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFtkb2NrZXJMb2dpblNlY3JldEFybl0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoZW5jcnlwdGlvbktleSkge1xuICAgICAgZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KGNvZGVCdWlsZFByb2plY3Qucm9sZSEpO1xuICAgIH1cblxuICAgIGNvbnN0IGVmZmVjdGl2ZVByb3ZpZGVyID0gcHJvdmlkZXIgPz8gVG9rZW5JbmplY3RhYmxlRG9ja2VyQnVpbGRlclByb3ZpZGVyLmdldE9yQ3JlYXRlKHRoaXMpO1xuICAgIGVmZmVjdGl2ZVByb3ZpZGVyLnJlZ2lzdGVyUHJvamVjdChjb2RlQnVpbGRQcm9qZWN0LCB0aGlzLmVjclJlcG9zaXRvcnksIGVuY3J5cHRpb25LZXkpO1xuXG4gICAgaWYgKHJlcGxpY2FSZWdpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMudmFsaWRhdGVSZXBsaWNhUmVnaW9ucyhyZXBsaWNhUmVnaW9ucyk7XG4gICAgICBlZmZlY3RpdmVQcm92aWRlci5yZWdpc3RlclJlcGxpY2F0aW9uKHRoaXMuZWNyUmVwb3NpdG9yeS5yZXBvc2l0b3J5TmFtZSwgcmVwbGljYVJlZ2lvbnMpO1xuICAgIH1cblxuICAgIC8vIFRoZSBDUidzIGNvbnN0cnVjdCBJRCBoYXMgYSBcIlYyXCIgc3VmZml4IHNvIHRoYXQgYSB2MS1kZXBsb3llZCBzdGFja1xuICAgIC8vIHVwZ3JhZGluZyB0byB2MiBzZWVzIGEgTkVXIHJlc291cmNlIChSZXBsYWNlKSwgbm90IGFuIGluLXBsYWNlIHVwZGF0ZVxuICAgIC8vIG9mIHRoZSBvbGQgYEJ1aWxkVHJpZ2dlclJlc291cmNlYC4gQ2xvdWRGb3JtYXRpb24gZm9yYmlkcyBtb2RpZnlpbmcgYVxuICAgIC8vIGN1c3RvbSByZXNvdXJjZSdzIGBTZXJ2aWNlVG9rZW5gIGluLXBsYWNlIChcIk1vZGlmeWluZyBzZXJ2aWNlIHRva2VuIGlzXG4gICAgLy8gbm90IGFsbG93ZWQuXCIpLCBhbmQgdGhlIHNlcnZpY2VUb2tlbiBjaGFuZ2VzIGZyb20gdjEncyBwZXItaW5zdGFuY2VcbiAgICAvLyBwcm92aWRlciB0byB2MidzIHNpbmdsZXRvbiBwcm92aWRlci4gUmVwbGFjZSBkb2RnZXMgdGhlIGNvbnN0cmFpbnQ6XG4gICAgLy8gdGhlIG9sZCBDUiBpcyBkZWxldGVkLCBhbmQgYSBuZXcgb25lIGlzIGNyZWF0ZWQgd2l0aCB0aGUgc2luZ2xldG9uJ3NcbiAgICAvLyBzZXJ2aWNlVG9rZW4g4oCUIGF0IHRoZSBjb3N0IG9mIG9uZSBmcmVzaCBidWlsZCBwZXIgYnVpbGRlciBvbiB1cGdyYWRlLlxuICAgIGNvbnN0IGJ1aWxkVHJpZ2dlclJlc291cmNlID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsICdCdWlsZFRyaWdnZXJSZXNvdXJjZVYyJywge1xuICAgICAgc2VydmljZVRva2VuOiBlZmZlY3RpdmVQcm92aWRlci5zZXJ2aWNlVG9rZW4sXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIFByb2plY3ROYW1lOiBjb2RlQnVpbGRQcm9qZWN0LnByb2plY3ROYW1lLFxuICAgICAgICBJbWFnZVRhZzogaW1hZ2VUYWcsXG4gICAgICAgIFRyaWdnZXI6IHNvdXJjZUFzc2V0LmFzc2V0SGFzaCxcbiAgICAgICAgUmV0YWluQnVpbGRMb2dzOiByZXRhaW5CdWlsZExvZ3MgPyAndHJ1ZScgOiAnZmFsc2UnLFxuICAgICAgICBSZXBvc2l0b3J5TmFtZTogdGhpcy5lY3JSZXBvc2l0b3J5LnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICBSZXBsaWNhUmVnaW9uczogSlNPTi5zdHJpbmdpZnkocmVwbGljYVJlZ2lvbnMpLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBidWlsZFRyaWdnZXJSZXNvdXJjZS5ub2RlLmFkZERlcGVuZGVuY3koY29kZUJ1aWxkUHJvamVjdCk7XG5cbiAgICAvLyBTQUZFVFk6IHJlZmVyZW5jZSBieSB0YWcsIG5vdCBkaWdlc3QuIFRoZSBsaWZlY3ljbGUgcG9saWN5IGFib3ZlIG5ldmVyXG4gICAgLy8gZGVsZXRlcyB0YWdnZWQgaW1hZ2VzLCBzbyB0aGUgZGlnZXN0IGJlaGluZCB0aGlzIHRhZyBpcyBndWFyYW50ZWVkIHRvXG4gICAgLy8gcmVtYWluIGluIEVDUiBmb3IgdGhlIGxpZmUgb2YgdGhlIHJlcG9zaXRvcnkuXG4gICAgY29uc3QgaW1hZ2VUYWdSZWYgPSBidWlsZFRyaWdnZXJSZXNvdXJjZS5nZXRBdHRTdHJpbmcoJ0ltYWdlVGFnJyk7XG4gICAgdGhpcy5pbWFnZVRhZyA9IGltYWdlVGFnUmVmO1xuICAgIHRoaXMucmVwb3NpdG9yeU5hbWUgPSB0aGlzLmVjclJlcG9zaXRvcnkucmVwb3NpdG9yeU5hbWU7XG4gICAgdGhpcy5jb250YWluZXJJbWFnZSA9IENvbnRhaW5lckltYWdlLmZyb21FY3JSZXBvc2l0b3J5KHRoaXMuZWNyUmVwb3NpdG9yeSwgaW1hZ2VUYWdSZWYpO1xuICAgIHRoaXMuZG9ja2VySW1hZ2VDb2RlID0gRG9ja2VySW1hZ2VDb2RlLmZyb21FY3IodGhpcy5lY3JSZXBvc2l0b3J5LCB7XG4gICAgICB0YWdPckRpZ2VzdDogaW1hZ2VUYWdSZWYsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRm9ybWF0IHRoZSBFQ1IgcmVwb3NpdG9yeSBVUkkgZm9yIGEgZ2l2ZW4gcmVnaW9uLiBUaGUgcmVnaW9uIG11c3RcbiAgICogYmUgZWl0aGVyIHRoZSBwcmltYXJ5IHJlZ2lvbiBvciBvbmUgb2YgYHJlcGxpY2FSZWdpb25zYC5cbiAgICovXG4gIHB1YmxpYyByZXBvc2l0b3J5VXJpRm9yKHJlZ2lvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICB0aGlzLmFzc2VydFJlZ2lvbklzS25vd24ocmVnaW9uKTtcbiAgICByZXR1cm4gYCR7dGhpcy5hY2NvdW50SWR9LmRrci5lY3IuJHtyZWdpb259LmFtYXpvbmF3cy5jb20vJHt0aGlzLnJlcG9zaXRvcnlOYW1lfWA7XG4gIH1cblxuICAvKipcbiAgICogSW1wb3J0IHRoZSByZXBsaWNhdGVkIHJlcG9zaXRvcnkgYXMgYW4gRUNTLWNvbXBhdGlibGVcbiAgICogYENvbnRhaW5lckltYWdlYCBpbiBhIGNvbnN1bWVyIHNjb3BlICh0eXBpY2FsbHkgYSBzdGFjayBpbiBgcmVnaW9uYCkuXG4gICAqXG4gICAqIFRoZSBjb25zdW1lcidzIHN0YWNrIG11c3QgaGF2ZSBgY3Jvc3NSZWdpb25SZWZlcmVuY2VzOiB0cnVlYCB3aGVuXG4gICAqIGByZWdpb25gIGRpZmZlcnMgZnJvbSB0aGUgYnVpbGRlcidzIHJlZ2lvbi5cbiAgICovXG4gIHB1YmxpYyBjb250YWluZXJJbWFnZUZvcihzY29wZTogQ29uc3RydWN0LCByZWdpb246IHN0cmluZyk6IENvbnRhaW5lckltYWdlIHtcbiAgICByZXR1cm4gQ29udGFpbmVySW1hZ2UuZnJvbUVjclJlcG9zaXRvcnkoXG4gICAgICB0aGlzLmltcG9ydFJlcG9Gb3Ioc2NvcGUsIHJlZ2lvbiksXG4gICAgICB0aGlzLmltYWdlVGFnLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogSW1wb3J0IHRoZSByZXBsaWNhdGVkIHJlcG9zaXRvcnkgYXMgYSBMYW1iZGEtY29tcGF0aWJsZVxuICAgKiBgRG9ja2VySW1hZ2VDb2RlYCBpbiBhIGNvbnN1bWVyIHNjb3BlICh0eXBpY2FsbHkgYSBzdGFjayBpbiBgcmVnaW9uYCkuXG4gICAqXG4gICAqIFRoZSBjb25zdW1lcidzIHN0YWNrIG11c3QgaGF2ZSBgY3Jvc3NSZWdpb25SZWZlcmVuY2VzOiB0cnVlYCB3aGVuXG4gICAqIGByZWdpb25gIGRpZmZlcnMgZnJvbSB0aGUgYnVpbGRlcidzIHJlZ2lvbi5cbiAgICovXG4gIHB1YmxpYyBkb2NrZXJJbWFnZUNvZGVGb3Ioc2NvcGU6IENvbnN0cnVjdCwgcmVnaW9uOiBzdHJpbmcpOiBEb2NrZXJJbWFnZUNvZGUge1xuICAgIHJldHVybiBEb2NrZXJJbWFnZUNvZGUuZnJvbUVjcih0aGlzLmltcG9ydFJlcG9Gb3Ioc2NvcGUsIHJlZ2lvbiksIHtcbiAgICAgIHRhZ09yRGlnZXN0OiB0aGlzLmltYWdlVGFnLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBpbXBvcnRSZXBvRm9yKHNjb3BlOiBDb25zdHJ1Y3QsIHJlZ2lvbjogc3RyaW5nKTogUmVwb3NpdG9yeSB7XG4gICAgdGhpcy5hc3NlcnRSZWdpb25Jc0tub3duKHJlZ2lvbik7XG4gICAgaWYgKHJlZ2lvbiA9PT0gdGhpcy5wcmltYXJ5UmVnaW9uKSByZXR1cm4gdGhpcy5lY3JSZXBvc2l0b3J5O1xuXG4gICAgLy8gSW5jbHVkZSB0aGUgYnVpbGRlcidzIG93biBub2RlLmFkZHIgaW4gdGhlIGltcG9ydCBpZCBzbyB0d28gZGlmZmVyZW50XG4gICAgLy8gYnVpbGRlcnMgaW1wb3J0aW5nIHRoZSBzYW1lIHJlZ2lvbiBpbnRvIHRoZSBzYW1lIHNjb3BlIGVhY2ggZ2V0IHRoZWlyXG4gICAgLy8gb3duIFJlcG9zaXRvcnkgY2hpbGQgKG90aGVyd2lzZSB0aGUgc2Vjb25kIGNhbGwgd291bGQgY29sbGlkZSB3aXRoIHRoZVxuICAgIC8vIGZpcnN0IGFuZCByZXR1cm4gdGhlIHdyb25nIGJ1aWxkZXIncyByZXBvKS5cbiAgICBjb25zdCBpbXBvcnRJZCA9IGBJbXBvcnRlZFJlcG8ke3JlZ2lvbn0ke3RoaXMubm9kZS5hZGRyfWA7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBzY29wZS5ub2RlLnRyeUZpbmRDaGlsZChpbXBvcnRJZCk7XG4gICAgaWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3RpbmcgYXMgUmVwb3NpdG9yeTtcblxuICAgIHJldHVybiBSZXBvc2l0b3J5LmZyb21SZXBvc2l0b3J5QXR0cmlidXRlcyhzY29wZSwgaW1wb3J0SWQsIHtcbiAgICAgIHJlcG9zaXRvcnlOYW1lOiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgcmVwb3NpdG9yeUFybjogU3RhY2sub2Yoc2NvcGUpLmZvcm1hdEFybih7XG4gICAgICAgIHNlcnZpY2U6ICdlY3InLFxuICAgICAgICByZXNvdXJjZTogJ3JlcG9zaXRvcnknLFxuICAgICAgICByZXNvdXJjZU5hbWU6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgIHJlZ2lvbixcbiAgICAgICAgYWNjb3VudDogdGhpcy5hY2NvdW50SWQsXG4gICAgICB9KSxcbiAgICB9KSBhcyBSZXBvc2l0b3J5O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3NlcnRSZWdpb25Jc0tub3duKHJlZ2lvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHJlZ2lvbiA9PT0gdGhpcy5wcmltYXJ5UmVnaW9uKSByZXR1cm47XG4gICAgaWYgKHRoaXMucmVwbGljYVJlZ2lvbnMuaW5jbHVkZXMocmVnaW9uKSkgcmV0dXJuO1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBSZWdpb24gXCIke3JlZ2lvbn1cIiBpcyBub3QgdGhlIHByaW1hcnkgcmVnaW9uICgke3RoaXMucHJpbWFyeVJlZ2lvbn0pIGAgK1xuICAgICAgYG9yIG9uZSBvZiB0aGUgY29uZmlndXJlZCByZXBsaWNhUmVnaW9ucyAoJHt0aGlzLnJlcGxpY2FSZWdpb25zLmpvaW4oJywgJykgfHwgJzxub25lPid9KS4gYCArXG4gICAgICAnQWRkIHRoZSByZWdpb24gdG8gdGhlIGJ1aWxkZXJcXCdzIHJlcGxpY2FSZWdpb25zIHByb3AgdG8gbWFrZSBpdCBhdmFpbGFibGUuJyxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVJlcGxpY2FSZWdpb25zKHJlcGxpY2FSZWdpb25zOiBzdHJpbmdbXSk6IHZvaWQge1xuICAgIGNvbnN0IHN0YWNrID0gU3RhY2sub2YodGhpcyk7XG4gICAgY29uc3QgcHJpbWFyeVBhcnRpdGlvbiA9IHN0YWNrLnBhcnRpdGlvbjtcbiAgICBmb3IgKGNvbnN0IHJlZ2lvbiBvZiByZXBsaWNhUmVnaW9ucykge1xuICAgICAgaWYgKHJlZ2lvbiA9PT0gdGhpcy5wcmltYXJ5UmVnaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgcmVwbGljYVJlZ2lvbnMgY2Fubm90IGluY2x1ZGUgdGhlIHByaW1hcnkgcmVnaW9uIFwiJHt0aGlzLnByaW1hcnlSZWdpb259XCIuIGAgK1xuICAgICAgICAgICdSZW1vdmUgaXQgZnJvbSB0aGUgbGlzdC4nLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgLy8gUGFydGl0aW9uIGNhbm5vdCBiZSBjbGVhbmx5IGluZmVycmVkIGZyb20gcmVnaW9uIGFsb25lIGF0IHN5bnRoIHRpbWVcbiAgICAgIC8vIChpdCdzIGEgQ0RLIHBzZXVkby1wYXJhbWV0ZXIgYW5kIG1heSBiZSBhIHRva2VuKS4gV2UgZG8gdGhlIGJlc3QtZWZmb3J0XG4gICAgICAvLyBjaGVjazogaWYgYm90aCBwYXJ0aXRpb24gdmFsdWVzIGFyZSBjb25jcmV0ZSBhbmQgdGhleSBkaWZmZXIsIGZhaWwuXG4gICAgICAvLyBDcm9zcy1wYXJ0aXRpb24gcmVwbGljYXRpb24gaXMgdW5zdXBwb3J0ZWQgYnkgRUNSLlxuICAgICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQocHJpbWFyeVBhcnRpdGlvbikpIHtcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRQYXJ0aXRpb24gPSBpbmZlclBhcnRpdGlvbihyZWdpb24pO1xuICAgICAgICBpZiAoZXhwZWN0ZWRQYXJ0aXRpb24gJiYgZXhwZWN0ZWRQYXJ0aXRpb24gIT09IHByaW1hcnlQYXJ0aXRpb24pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnQ3Jvc3MtcGFydGl0aW9uIEVDUiByZXBsaWNhdGlvbiBpcyBub3Qgc3VwcG9ydGVkLiAnICtcbiAgICAgICAgICAgIGBQcmltYXJ5IHBhcnRpdGlvbiBpcyBcIiR7cHJpbWFyeVBhcnRpdGlvbn1cIiBidXQgcmVwbGljYSByZWdpb24gYCArXG4gICAgICAgICAgICBgXCIke3JlZ2lvbn1cIiBhcHBlYXJzIHRvIGJlIGluIHBhcnRpdGlvbiBcIiR7ZXhwZWN0ZWRQYXJ0aXRpb259XCIuYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBncmFudEVjckFjY2Vzcyhwcm9qZWN0OiBQcm9qZWN0KTogdm9pZCB7XG4gICAgdGhpcy5lY3JSZXBvc2l0b3J5LmdyYW50UHVsbFB1c2gocHJvamVjdCk7XG4gICAgcHJvamVjdC5hZGRUb1JvbGVQb2xpY3koXG4gICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICdlY3I6R2V0QXV0aG9yaXphdGlvblRva2VuJyxcbiAgICAgICAgICAnZWNyOkdldERvd25sb2FkVXJsRm9yTGF5ZXInLFxuICAgICAgICAgICdlY3I6QmF0Y2hDaGVja0xheWVyQXZhaWxhYmlsaXR5JyxcbiAgICAgICAgICAnZWNyOkJhdGNoR2V0SW1hZ2UnLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ3JhbnRQdWxsVGhyb3VnaENhY2hlQWNjZXNzKHByb2plY3Q6IFByb2plY3QsIHByZWZpeGVzOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGlmICghcHJlZml4ZXMgfHwgcHJlZml4ZXMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgY29uc3Qgc3RhY2sgPSBTdGFjay5vZih0aGlzKTtcbiAgICBwcm9qZWN0LmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ2VjcjpCYXRjaEdldEltYWdlJyxcbiAgICAgICAgICAnZWNyOkdldERvd25sb2FkVXJsRm9yTGF5ZXInLFxuICAgICAgICAgICdlY3I6QmF0Y2hDaGVja0xheWVyQXZhaWxhYmlsaXR5JyxcbiAgICAgICAgICAnZWNyOkJhdGNoSW1wb3J0VXBzdHJlYW1JbWFnZScsXG4gICAgICAgICAgJ2VjcjpDcmVhdGVSZXBvc2l0b3J5JyxcbiAgICAgICAgXSxcbiAgICAgICAgcmVzb3VyY2VzOiBwcmVmaXhlcy5tYXAoXG4gICAgICAgICAgKHByZWZpeCkgPT4gYGFybjphd3M6ZWNyOiR7c3RhY2sucmVnaW9ufToke3N0YWNrLmFjY291bnR9OnJlcG9zaXRvcnkvJHtwcmVmaXh9LypgLFxuICAgICAgICApLFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ3JhbnRCdWlsZExvZ3NBY2Nlc3MocHJvamVjdDogUHJvamVjdCwgcmV0YWluQnVpbGRMb2dzOiBib29sZWFuKTogdm9pZCB7XG4gICAgaWYgKCFyZXRhaW5CdWlsZExvZ3MpIHJldHVybjtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIHByb2plY3QuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFsnbG9nczpDcmVhdGVMb2dHcm91cCcsICdsb2dzOkNyZWF0ZUxvZ1N0cmVhbScsICdsb2dzOlB1dExvZ0V2ZW50cyddLFxuICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICBgYXJuOmF3czpsb2dzOiR7c3RhY2sucmVnaW9ufToke3N0YWNrLmFjY291bnR9OmxvZy1ncm91cDoke0JVSUxEX0xPR19HUk9VUF9QUkVGSVh9JHtwcm9qZWN0LnByb2plY3ROYW1lfWAsXG4gICAgICAgICAgYGFybjphd3M6bG9nczoke3N0YWNrLnJlZ2lvbn06JHtzdGFjay5hY2NvdW50fTpsb2ctZ3JvdXA6JHtCVUlMRF9MT0dfR1JPVVBfUFJFRklYfSR7cHJvamVjdC5wcm9qZWN0TmFtZX06KmAsXG4gICAgICAgIF0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogQmVzdC1lZmZvcnQgcGFydGl0aW9uIGluZmVyZW5jZSBmcm9tIGFuIEFXUyByZWdpb24gbmFtZS4gUmV0dXJuc1xuICogdW5kZWZpbmVkIGlmIHRoZSByZWdpb24gZG9lc24ndCBsb29rIGxpa2UgYSBrbm93biBwYXJ0aXRpb24gcHJlZml4IOKAlFxuICogY2FsbGVycyBzaG91bGQgdHJlYXQgdGhhdCBhcyBcInNraXAgdGhlIHBhcnRpdGlvbiBjaGVja1wiLlxuICovXG5mdW5jdGlvbiBpbmZlclBhcnRpdGlvbihyZWdpb246IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChyZWdpb24uc3RhcnRzV2l0aCgnY24tJykpIHJldHVybiAnYXdzLWNuJztcbiAgaWYgKHJlZ2lvbi5zdGFydHNXaXRoKCd1cy1nb3YtJykpIHJldHVybiAnYXdzLXVzLWdvdic7XG4gIGlmIChyZWdpb24uc3RhcnRzV2l0aCgndXMtaXNvLScpKSByZXR1cm4gJ2F3cy1pc28nO1xuICBpZiAocmVnaW9uLnN0YXJ0c1dpdGgoJ3VzLWlzb2ItJykpIHJldHVybiAnYXdzLWlzby1iJztcbiAgaWYgKC9eW2Etel17Mn0tW2Etel0rLVxcZCskLy50ZXN0KHJlZ2lvbikpIHJldHVybiAnYXdzJztcbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Duration } from 'aws-cdk-lib';
|
|
2
|
+
import { Runtime } from 'aws-cdk-lib/aws-lambda';
|
|
3
|
+
export declare const LAMBDA_RUNTIME: Runtime;
|
|
4
|
+
export declare const LAMBDA_TIMEOUT: Duration;
|
|
5
|
+
export declare const DEFAULT_QUERY_INTERVAL: Duration;
|
|
6
|
+
export declare const BUILD_LOG_GROUP_PREFIX = "/docker-builder/";
|
|
7
|
+
export declare const PROVIDER_SINGLETON_ID = "TokenInjectableDockerBuilderProvider";
|
package/lib/constants.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROVIDER_SINGLETON_ID = exports.BUILD_LOG_GROUP_PREFIX = exports.DEFAULT_QUERY_INTERVAL = exports.LAMBDA_TIMEOUT = exports.LAMBDA_RUNTIME = void 0;
|
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
|
+
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
|
6
|
+
exports.LAMBDA_RUNTIME = aws_lambda_1.Runtime.NODEJS_22_X;
|
|
7
|
+
exports.LAMBDA_TIMEOUT = aws_cdk_lib_1.Duration.minutes(15);
|
|
8
|
+
exports.DEFAULT_QUERY_INTERVAL = aws_cdk_lib_1.Duration.seconds(30);
|
|
9
|
+
exports.BUILD_LOG_GROUP_PREFIX = '/docker-builder/';
|
|
10
|
+
exports.PROVIDER_SINGLETON_ID = 'TokenInjectableDockerBuilderProvider';
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBdUM7QUFDdkMsdURBQWlEO0FBRXBDLFFBQUEsY0FBYyxHQUFHLG9CQUFPLENBQUMsV0FBVyxDQUFDO0FBQ3JDLFFBQUEsY0FBYyxHQUFHLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3RDLFFBQUEsc0JBQXNCLEdBQUcsc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDOUMsUUFBQSxzQkFBc0IsR0FBRyxrQkFBa0IsQ0FBQztBQUM1QyxRQUFBLHFCQUFxQixHQUFHLHNDQUFzQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHVyYXRpb24gfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBSdW50aW1lIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5cbmV4cG9ydCBjb25zdCBMQU1CREFfUlVOVElNRSA9IFJ1bnRpbWUuTk9ERUpTXzIyX1g7XG5leHBvcnQgY29uc3QgTEFNQkRBX1RJTUVPVVQgPSBEdXJhdGlvbi5taW51dGVzKDE1KTtcbmV4cG9ydCBjb25zdCBERUZBVUxUX1FVRVJZX0lOVEVSVkFMID0gRHVyYXRpb24uc2Vjb25kcygzMCk7XG5leHBvcnQgY29uc3QgQlVJTERfTE9HX0dST1VQX1BSRUZJWCA9ICcvZG9ja2VyLWJ1aWxkZXIvJztcbmV4cG9ydCBjb25zdCBQUk9WSURFUl9TSU5HTEVUT05fSUQgPSAnVG9rZW5JbmplY3RhYmxlRG9ja2VyQnVpbGRlclByb3ZpZGVyJztcbiJdfQ==
|
package/lib/ecr.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Repository } from 'aws-cdk-lib/aws-ecr';
|
|
2
|
+
import { Key } from 'aws-cdk-lib/aws-kms';
|
|
3
|
+
import { Construct } from 'constructs';
|
|
4
|
+
export interface BuilderEcrRepositoryOptions {
|
|
5
|
+
readonly kmsEncryption: boolean;
|
|
6
|
+
readonly encryptionKey?: Key;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Create an ECR repository for a builder.
|
|
10
|
+
*
|
|
11
|
+
* SAFETY: tagged images are never deleted. Lambda pins images by digest
|
|
12
|
+
* internally, so deleting an in-use tagged image would make the next Lambda
|
|
13
|
+
* config update fail with "Image ID cannot be found". Untagged images are
|
|
14
|
+
* cleaned up after 30 days.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createBuilderEcrRepository(scope: Construct, id: string, options: BuilderEcrRepositoryOptions): Repository;
|
package/lib/ecr.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBuilderEcrRepository = createBuilderEcrRepository;
|
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
|
+
const aws_ecr_1 = require("aws-cdk-lib/aws-ecr");
|
|
6
|
+
/**
|
|
7
|
+
* Create an ECR repository for a builder.
|
|
8
|
+
*
|
|
9
|
+
* SAFETY: tagged images are never deleted. Lambda pins images by digest
|
|
10
|
+
* internally, so deleting an in-use tagged image would make the next Lambda
|
|
11
|
+
* config update fail with "Image ID cannot be found". Untagged images are
|
|
12
|
+
* cleaned up after 30 days.
|
|
13
|
+
*/
|
|
14
|
+
function createBuilderEcrRepository(scope, id, options) {
|
|
15
|
+
const { kmsEncryption, encryptionKey } = options;
|
|
16
|
+
return new aws_ecr_1.Repository(scope, id, {
|
|
17
|
+
lifecycleRules: [
|
|
18
|
+
{
|
|
19
|
+
rulePriority: 1,
|
|
20
|
+
description: 'Remove untagged images after 30 days',
|
|
21
|
+
tagStatus: aws_ecr_1.TagStatus.UNTAGGED,
|
|
22
|
+
maxImageAge: aws_cdk_lib_1.Duration.days(30),
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
encryption: kmsEncryption ? aws_ecr_1.RepositoryEncryption.KMS : aws_ecr_1.RepositoryEncryption.AES_256,
|
|
26
|
+
encryptionKey: kmsEncryption ? encryptionKey : undefined,
|
|
27
|
+
imageScanOnPush: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Vjci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWtCQSxnRUFvQkM7QUF0Q0QsNkNBQXVDO0FBQ3ZDLGlEQUFrRjtBQVNsRjs7Ozs7OztHQU9HO0FBQ0gsU0FBZ0IsMEJBQTBCLENBQ3hDLEtBQWdCLEVBQ2hCLEVBQVUsRUFDVixPQUFvQztJQUVwQyxNQUFNLEVBQUUsYUFBYSxFQUFFLGFBQWEsRUFBRSxHQUFHLE9BQU8sQ0FBQztJQUVqRCxPQUFPLElBQUksb0JBQVUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1FBQy9CLGNBQWMsRUFBRTtZQUNkO2dCQUNFLFlBQVksRUFBRSxDQUFDO2dCQUNmLFdBQVcsRUFBRSxzQ0FBc0M7Z0JBQ25ELFNBQVMsRUFBRSxtQkFBUyxDQUFDLFFBQVE7Z0JBQzdCLFdBQVcsRUFBRSxzQkFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7YUFDL0I7U0FDRjtRQUNELFVBQVUsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLDhCQUFvQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsOEJBQW9CLENBQUMsT0FBTztRQUNuRixhQUFhLEVBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLFNBQVM7UUFDeEQsZUFBZSxFQUFFLElBQUk7S0FDdEIsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IER1cmF0aW9uIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgUmVwb3NpdG9yeSwgUmVwb3NpdG9yeUVuY3J5cHRpb24sIFRhZ1N0YXR1cyB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3InO1xuaW1wb3J0IHsgS2V5IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWttcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcblxuZXhwb3J0IGludGVyZmFjZSBCdWlsZGVyRWNyUmVwb3NpdG9yeU9wdGlvbnMge1xuICByZWFkb25seSBrbXNFbmNyeXB0aW9uOiBib29sZWFuO1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5PzogS2V5O1xufVxuXG4vKipcbiAqIENyZWF0ZSBhbiBFQ1IgcmVwb3NpdG9yeSBmb3IgYSBidWlsZGVyLlxuICpcbiAqIFNBRkVUWTogdGFnZ2VkIGltYWdlcyBhcmUgbmV2ZXIgZGVsZXRlZC4gTGFtYmRhIHBpbnMgaW1hZ2VzIGJ5IGRpZ2VzdFxuICogaW50ZXJuYWxseSwgc28gZGVsZXRpbmcgYW4gaW4tdXNlIHRhZ2dlZCBpbWFnZSB3b3VsZCBtYWtlIHRoZSBuZXh0IExhbWJkYVxuICogY29uZmlnIHVwZGF0ZSBmYWlsIHdpdGggXCJJbWFnZSBJRCBjYW5ub3QgYmUgZm91bmRcIi4gVW50YWdnZWQgaW1hZ2VzIGFyZVxuICogY2xlYW5lZCB1cCBhZnRlciAzMCBkYXlzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQnVpbGRlckVjclJlcG9zaXRvcnkoXG4gIHNjb3BlOiBDb25zdHJ1Y3QsXG4gIGlkOiBzdHJpbmcsXG4gIG9wdGlvbnM6IEJ1aWxkZXJFY3JSZXBvc2l0b3J5T3B0aW9ucyxcbik6IFJlcG9zaXRvcnkge1xuICBjb25zdCB7IGttc0VuY3J5cHRpb24sIGVuY3J5cHRpb25LZXkgfSA9IG9wdGlvbnM7XG5cbiAgcmV0dXJuIG5ldyBSZXBvc2l0b3J5KHNjb3BlLCBpZCwge1xuICAgIGxpZmVjeWNsZVJ1bGVzOiBbXG4gICAgICB7XG4gICAgICAgIHJ1bGVQcmlvcml0eTogMSxcbiAgICAgICAgZGVzY3JpcHRpb246ICdSZW1vdmUgdW50YWdnZWQgaW1hZ2VzIGFmdGVyIDMwIGRheXMnLFxuICAgICAgICB0YWdTdGF0dXM6IFRhZ1N0YXR1cy5VTlRBR0dFRCxcbiAgICAgICAgbWF4SW1hZ2VBZ2U6IER1cmF0aW9uLmRheXMoMzApLFxuICAgICAgfSxcbiAgICBdLFxuICAgIGVuY3J5cHRpb246IGttc0VuY3J5cHRpb24gPyBSZXBvc2l0b3J5RW5jcnlwdGlvbi5LTVMgOiBSZXBvc2l0b3J5RW5jcnlwdGlvbi5BRVNfMjU2LFxuICAgIGVuY3J5cHRpb25LZXk6IGttc0VuY3J5cHRpb24gPyBlbmNyeXB0aW9uS2V5IDogdW5kZWZpbmVkLFxuICAgIGltYWdlU2Nhbk9uUHVzaDogdHJ1ZSxcbiAgfSk7XG59XG4iXX0=
|