@raindancers/raindancers-crew 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,383 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.EcsCrewHost = void 0;
37
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
41
+ const autoscaling = __importStar(require("aws-cdk-lib/aws-autoscaling"));
42
+ const ec2 = __importStar(require("aws-cdk-lib/aws-ec2"));
43
+ const ecs = __importStar(require("aws-cdk-lib/aws-ecs"));
44
+ const iam = __importStar(require("aws-cdk-lib/aws-iam"));
45
+ const constructs_1 = require("constructs");
46
+ const fargate_crew_1 = require("./fargate-crew");
47
+ const fargate_crew_base_1 = require("./fargate-crew-base");
48
+ const remote_crew_instance_props_1 = require("./remote-crew-instance-props");
49
+ const STACK_TAG_RE = /^[a-zA-Z0-9-]{1,51}$/;
50
+ const CREW_RE = /^[a-z0-9]([a-z0-9-]{0,30}[a-z0-9])?$/;
51
+ const DEFAULT_STACK_TAG = 'kirocrew';
52
+ const DEFAULT_CREW_COUNT = 1;
53
+ const MAX_CREW_COUNT = 8;
54
+ const DEFAULT_ROOT_VOLUME_GB = 60;
55
+ const DEFAULT_CREW_VOLUME_GB = 20;
56
+ const DEFAULT_MEMORY_RESERVATION_MIB = 1024;
57
+ const DEFAULT_MEMORY_HARD_LIMIT_MIB = 2048;
58
+ /**
59
+ * One self-provisioned EC2 host running the ECS agent, hosting `crewCount`
60
+ * Kiro Crew instances as ECS-on-EC2 container tasks.
61
+ *
62
+ * The host registers to the {@link FargateCrewBase} cluster and does the NAT
63
+ * for the crew tasks itself, so the tasks stay fully private with no public
64
+ * IPs and no NAT Gateway, fck-nat, VPC endpoints, or ALB. Each task runs in
65
+ * awsvpc mode with its own ENI and private VPC IP; each crew keeps its durable
66
+ * `~/.kiro/crew` state on its own encrypted EBS volume that survives instance
67
+ * replacement.
68
+ *
69
+ * Isolation is container-level (shared kernel), accepted as sufficient:
70
+ * Graviton Nitro protects the box from other AWS tenants, containers cover
71
+ * crew-to-crew separation. See the host-OOM caution: hard per-task memory caps
72
+ * bound each crew's ceiling but a busy crew can still pressure siblings when
73
+ * the sum of actual usage exceeds physical RAM.
74
+ *
75
+ * `crewCount` defaults to 1, identical to the single-crew shape, so a plain
76
+ * instantiation with no new props gains no extra resources.
77
+ */
78
+ class EcsCrewHost extends constructs_1.Construct {
79
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "@raindancers/raindancers-crew.EcsCrewHost", version: "0.0.2" };
80
+ /** The shared ECS scaffolding (cluster + egress-only task SG). */
81
+ base;
82
+ /** The size-1 Auto Scaling Group holding the single ECS-registered EC2 host. */
83
+ autoScalingGroup;
84
+ /** The capacity provider registering the host with the cluster. */
85
+ capacityProvider;
86
+ /** The host instance's IAM role (carries the permissions boundary). */
87
+ role;
88
+ /** The host's SSM-only security group (no inbound). */
89
+ hostSecurityGroup;
90
+ /** The per-crew scaffolding (roles + log group), one per crew. */
91
+ crews;
92
+ /** The per-crew EC2 services. */
93
+ services;
94
+ /** The per-crew durable data volumes (device/label/mount metadata). */
95
+ dataVolumes;
96
+ /** The discovery tag value written as `kirocrew:ecs-host`. */
97
+ stackTag;
98
+ /** The resolved crew names. */
99
+ crewNames;
100
+ constructor(scope, id, props) {
101
+ super(scope, id);
102
+ const stackTag = props.stackTag ?? DEFAULT_STACK_TAG;
103
+ if (!STACK_TAG_RE.test(stackTag)) {
104
+ throw new Error(`stackTag must match ${STACK_TAG_RE} (got '${stackTag}')`);
105
+ }
106
+ this.stackTag = stackTag;
107
+ const crewCount = props.crewCount ?? DEFAULT_CREW_COUNT;
108
+ if (!Number.isInteger(crewCount) || crewCount < 1 || crewCount > MAX_CREW_COUNT) {
109
+ throw new Error(`crewCount must be an integer 1..${MAX_CREW_COUNT} (got ${crewCount}); ` +
110
+ 'awsvpc needs (crewCount + 1) ENIs to fit the instance type');
111
+ }
112
+ const crewNames = props.crews ?? defaultCrewNames(crewCount);
113
+ if (crewNames.length !== crewCount) {
114
+ throw new Error(`crews must list exactly crewCount (${crewCount}) names (got ${crewNames.length})`);
115
+ }
116
+ for (const crew of crewNames) {
117
+ if (!CREW_RE.test(crew)) {
118
+ throw new Error(`crew name must match ${CREW_RE} (got '${crew}'); it derives the ` +
119
+ 'log group, roles, and secret namespace');
120
+ }
121
+ }
122
+ if (new Set(crewNames).size !== crewNames.length) {
123
+ throw new Error(`crew names must be unique (got ${crewNames.join(', ')})`);
124
+ }
125
+ this.crewNames = crewNames;
126
+ const arch = props.architecture ?? remote_crew_instance_props_1.CrewArchitecture.ARM64;
127
+ const fargateArch = arch === remote_crew_instance_props_1.CrewArchitecture.ARM64
128
+ ? fargate_crew_base_1.FargateCpuArchitecture.ARM64
129
+ : fargate_crew_base_1.FargateCpuArchitecture.X86_64;
130
+ // --- Shared ECS scaffolding: reuse FargateCrewBase for the cluster and the
131
+ // egress-only task security group, so there is one code path for the
132
+ // cluster the tasks register to.
133
+ this.base = new fargate_crew_base_1.FargateCrewBase(this, 'Base', {
134
+ vpc: props.vpc,
135
+ vpcSubnets: props.taskSubnets,
136
+ cpuArchitecture: fargateArch,
137
+ stackTag,
138
+ });
139
+ // --- Host instance role: SSM core + required boundary, mirroring
140
+ // RemoteCrewInstance. Plus the ECS-agent register/telemetry permissions so
141
+ // this box can join the cluster and run tasks.
142
+ this.role = new iam.Role(this, 'HostRole', {
143
+ assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
144
+ permissionsBoundary: iam.ManagedPolicy.fromManagedPolicyArn(this, 'Boundary', props.permissionsBoundaryArn),
145
+ managedPolicies: [
146
+ iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'),
147
+ // The ECS container-instance role: RegisterContainerInstance, Poll,
148
+ // Submit*, and the ECR/log actions the agent needs. Standard for an
149
+ // ECS-on-EC2 capacity host.
150
+ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceforEC2Role'),
151
+ ],
152
+ });
153
+ // --- Host security group: SSM-only, no inbound. Egress open for image
154
+ // pulls, the model endpoint, and forwarding the tasks' NATed traffic.
155
+ this.hostSecurityGroup = new ec2.SecurityGroup(this, 'HostSecurityGroup', {
156
+ vpc: props.vpc,
157
+ description: `KiroCrew ECS host ${stackTag} - SSM-only (no inbound), does NAT for crew tasks`,
158
+ allowAllOutbound: true,
159
+ });
160
+ // --- Arch-aware ECS-optimized Amazon Linux 2023 AMI (the agent is
161
+ // pre-installed), resolved via the public SSM parameter, no hardcoded id.
162
+ const amiHardwareType = arch === remote_crew_instance_props_1.CrewArchitecture.ARM64
163
+ ? ecs.AmiHardwareType.ARM
164
+ : ecs.AmiHardwareType.STANDARD;
165
+ const machineImage = ecs.EcsOptimizedImage.amazonLinux2023(amiHardwareType);
166
+ const instanceType = props.instanceType ??
167
+ (arch === remote_crew_instance_props_1.CrewArchitecture.ARM64
168
+ ? new ec2.InstanceType('m7g.2xlarge')
169
+ : new ec2.InstanceType('m7i.2xlarge'));
170
+ // --- Per-crew durable data volumes: one gp3 EBS each, encrypted,
171
+ // deleteOnTermination:false, resolved in the bootstrap by a stable LABEL
172
+ // (never /dev/sdf, which the Nitro NVMe layer renames).
173
+ const volumeType = props.crewDataVolumeType ?? ec2.EbsDeviceVolumeType.GP3;
174
+ const volumeSize = props.crewDataVolumeSizeGb ?? DEFAULT_CREW_VOLUME_GB;
175
+ this.dataVolumes = crewNames.map((crew, i) => ({
176
+ crew,
177
+ // Device letters f.. (sdf, sdg, ...) are attach-time hints; the kernel
178
+ // renames them on Nitro, so the bootstrap ignores them and uses label.
179
+ deviceName: `/dev/sd${String.fromCharCode('f'.charCodeAt(0) + i)}`,
180
+ label: `crew-${crew}`,
181
+ mountPath: `/var/lib/kirocrew/${crew}`,
182
+ }));
183
+ // The ASG uses the autoscaling module's own BlockDevice types (distinct
184
+ // from ec2's). The public crewDataVolumeType prop stays ec2-typed for
185
+ // library consistency; translate it by its shared string value here.
186
+ const asgVolumeType = volumeType;
187
+ const rootBlockDevice = {
188
+ deviceName: '/dev/xvda',
189
+ volume: autoscaling.BlockDeviceVolume.ebs(props.rootVolumeSizeGb ?? DEFAULT_ROOT_VOLUME_GB, {
190
+ volumeType: autoscaling.EbsDeviceVolumeType.GP3,
191
+ encrypted: true,
192
+ deleteOnTermination: true,
193
+ }),
194
+ };
195
+ const crewBlockDevices = this.dataVolumes.map((v) => ({
196
+ deviceName: v.deviceName,
197
+ volume: autoscaling.BlockDeviceVolume.ebs(volumeSize, {
198
+ volumeType: asgVolumeType,
199
+ encrypted: true,
200
+ // The whole point: a crew's memory outlives an instance replacement.
201
+ deleteOnTermination: false,
202
+ }),
203
+ }));
204
+ // --- UserData: a small header the bootstrap body reads (per-crew volume
205
+ // labels + mount paths, ECS cluster name), then the ECS-host bootstrap
206
+ // asset (host NAT + resolve-by-label EBS mount). The AsgCapacityProvider
207
+ // below ALSO appends the ECS-cluster join to this UserData; writing
208
+ // ECS_CLUSTER here is a harmless idempotent belt-and-braces.
209
+ const bootstrapBody = fs.readFileSync(resolveAsset('ecs-host-bootstrap.sh'), 'utf8');
210
+ const userData = ec2.UserData.forLinux();
211
+ userData.addCommands('ECS_CLUSTER=' + shellQuote(this.base.cluster.clusterName), 'CREW_COUNT=' + String(crewCount), 'CREW_VOLUME_LABELS=' + shellQuote(this.dataVolumes.map((v) => v.label).join(' ')), 'CREW_MOUNT_PATHS=' + shellQuote(this.dataVolumes.map((v) => v.mountPath).join(' ')), 'export ECS_CLUSTER CREW_COUNT CREW_VOLUME_LABELS CREW_MOUNT_PATHS');
212
+ userData.addCommands(bootstrapBody);
213
+ // --- The single ECS-registered host, as a size-1 Auto Scaling Group behind
214
+ // an AsgCapacityProvider. A size-1 ASG (min=max=desired=1) is still ONE
215
+ // self-provisioned EC2 host and still ECS-on-EC2 (no Fargate); the capacity
216
+ // provider is what registers that capacity with the cluster so the L2
217
+ // Ec2Services below can schedule onto it. IMDSv2 enforced (a
218
+ // prompt-injectable agent must not read role creds via IMDSv1), encrypted
219
+ // gp3 root, plus the per-crew durable data volumes.
220
+ this.autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'HostAsg', {
221
+ vpc: props.vpc,
222
+ vpcSubnets: props.hostSubnets ?? { subnetType: ec2.SubnetType.PUBLIC },
223
+ instanceType,
224
+ machineImage,
225
+ role: this.role,
226
+ securityGroup: this.hostSecurityGroup,
227
+ userData,
228
+ requireImdsv2: true,
229
+ minCapacity: 1,
230
+ maxCapacity: 1,
231
+ desiredCapacity: 1,
232
+ // The host is in the PUBLIC subnet and carries the public IP so it
233
+ // egresses via the IGW and can NAT the tasks. Tasks get none.
234
+ associatePublicIpAddress: true,
235
+ blockDevices: [rootBlockDevice, ...crewBlockDevices],
236
+ });
237
+ aws_cdk_lib_1.Tags.of(this.autoScalingGroup).add('Name', `kirocrew-ecs-host-${stackTag}`);
238
+ // --- Host does the NAT: it must forward packets that are neither from nor
239
+ // to its own address, which requires source/dest check DISABLED on the host
240
+ // ENI. CloudFormation cannot set SourceDestCheck on an ASG-launched instance
241
+ // declaratively, so the bootstrap disables it on the host itself via
242
+ // ec2:ModifyInstanceAttribute (scoped by an instance-tag condition so the
243
+ // host can only ever modify a KiroCrew ECS host, not an arbitrary instance).
244
+ // The bootstrap also sets ip_forward=1 and the iptables MASQUERADE rule.
245
+ this.role.addToPolicy(new iam.PolicyStatement({
246
+ actions: ['ec2:ModifyInstanceAttribute'],
247
+ resources: ['*'],
248
+ conditions: {
249
+ StringEquals: { 'aws:ResourceTag/kirocrew:ecs-host': stackTag },
250
+ },
251
+ }));
252
+ // --- Register this ASG's capacity with the cluster. This is what makes the
253
+ // cluster have Ec2 capacity as far as CDK's Ec2Service validation is
254
+ // concerned, and it appends the ECS-cluster join to the host UserData.
255
+ this.capacityProvider = new ecs.AsgCapacityProvider(this, 'HostCapacity', {
256
+ autoScalingGroup: this.autoScalingGroup,
257
+ // The instances are long-lived crew hosts; do not let ECS scale them in
258
+ // or terminate them from under running crews.
259
+ enableManagedTerminationProtection: false,
260
+ });
261
+ this.base.cluster.addAsgCapacityProvider(this.capacityProvider);
262
+ // --- Per-crew: FargateCrew scaffolding (roles + log group), an EC2 task
263
+ // definition (awsvpc), a container definition, and an Ec2Service.
264
+ this.crews = [];
265
+ this.services = [];
266
+ const crewImage = props.crewImage ?? 'public.ecr.aws/kirocrew/crew:latest';
267
+ const memoryReservationMiB = props.crewMemoryReservationMiB ?? DEFAULT_MEMORY_RESERVATION_MIB;
268
+ const memoryHardLimitMiB = props.crewMemoryHardLimitMiB ?? DEFAULT_MEMORY_HARD_LIMIT_MIB;
269
+ if (memoryReservationMiB > memoryHardLimitMiB) {
270
+ throw new Error(`crewMemoryReservationMiB (${memoryReservationMiB}) must not exceed ` +
271
+ `crewMemoryHardLimitMiB (${memoryHardLimitMiB}): the soft reservation ` +
272
+ 'cannot be higher than the hard ceiling');
273
+ }
274
+ crewNames.forEach((crew, i) => {
275
+ const dataVolume = this.dataVolumes[i];
276
+ const crewScaffold = new fargate_crew_1.FargateCrew(this, `Crew${i}`, {
277
+ crew,
278
+ logRetentionDays: props.logRetentionDays,
279
+ permissionsBoundaryArn: props.crewPermissionsBoundaryArn,
280
+ ecrRepositoryArn: props.ecrRepositoryArn,
281
+ backupBucket: props.backupBucket,
282
+ });
283
+ this.crews.push(crewScaffold);
284
+ const taskDef = new ecs.Ec2TaskDefinition(this, `TaskDef${i}`, {
285
+ // awsvpc: each task gets its own ENI + private VPC IP.
286
+ networkMode: ecs.NetworkMode.AWS_VPC,
287
+ taskRole: crewScaffold.taskRole,
288
+ executionRole: crewScaffold.executionRole,
289
+ // No runtimePlatform: an EC2 task's architecture is that of the host it
290
+ // lands on (the arm64 ECS-optimized AMI here), not a task-def field
291
+ // (that is Fargate-only).
292
+ // A host volume mapping the crew's mounted EBS path so ~/.kiro/crew is
293
+ // durable across task/instance replacement.
294
+ volumes: [
295
+ {
296
+ name: `crew-data-${crew}`,
297
+ host: { sourcePath: dataVolume.mountPath },
298
+ },
299
+ ],
300
+ });
301
+ const container = taskDef.addContainer(`Crew${i}Container`, {
302
+ image: ecs.ContainerImage.fromRegistry(crewImage),
303
+ // SOFT reservation for scheduling; idle crews cost little.
304
+ memoryReservationMiB,
305
+ // HARD cap so a runaway crew cannot exceed its ceiling (host-OOM
306
+ // blast-radius caution in the README).
307
+ memoryLimitMiB: memoryHardLimitMiB,
308
+ // Optional soft CPU shares; unset => shared CPU under contention.
309
+ cpu: props.crewCpuShares,
310
+ logging: ecs.LogDriver.awsLogs({
311
+ streamPrefix: crew,
312
+ logGroup: crewScaffold.logGroup,
313
+ }),
314
+ });
315
+ container.addMountPoints({
316
+ containerPath: '/home/kirocrew/.kiro/crew',
317
+ sourceVolume: `crew-data-${crew}`,
318
+ readOnly: false,
319
+ });
320
+ const service = new ecs.Ec2Service(this, `Service${i}`, {
321
+ cluster: this.base.cluster,
322
+ taskDefinition: taskDef,
323
+ desiredCount: 1,
324
+ // awsvpc placement: the PRIVATE task subnet, the egress-only task SG,
325
+ // no public IP (tasks are fully private; the host NATs their egress).
326
+ securityGroups: [this.base.securityGroup],
327
+ vpcSubnets: props.taskSubnets ?? {
328
+ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
329
+ },
330
+ });
331
+ // The service depends on the host capacity being registered.
332
+ service.node.addDependency(this.capacityProvider);
333
+ this.services.push(service);
334
+ });
335
+ // Tag the ASG (tags propagate to launched instances by default), so the
336
+ // kirocrew:ecs-host tag the ModifyInstanceAttribute condition keys off is
337
+ // present on the host, and the SG.
338
+ for (const taggable of [this.autoScalingGroup, this.hostSecurityGroup]) {
339
+ aws_cdk_lib_1.Tags.of(taggable).add('kirocrew:managed', 'true');
340
+ aws_cdk_lib_1.Tags.of(taggable).add('kirocrew:ecs-host', stackTag);
341
+ }
342
+ }
343
+ /** The region the host runs in (read from the stack env, never a prop). */
344
+ get region() {
345
+ return aws_cdk_lib_1.Stack.of(this).region;
346
+ }
347
+ }
348
+ exports.EcsCrewHost = EcsCrewHost;
349
+ /** Generate default crew names crew-1 .. crew-<count>. */
350
+ function defaultCrewNames(count) {
351
+ const names = [];
352
+ for (let i = 1; i <= count; i++) {
353
+ names.push(`crew-${i}`);
354
+ }
355
+ return names;
356
+ }
357
+ /** Single-quote a literal for safe embedding; pass CDK tokens through. */
358
+ function shellQuote(value) {
359
+ if (aws_cdk_lib_1.Token.isUnresolved(value)) {
360
+ return value;
361
+ }
362
+ return `'${value.replace(/'/g, "'\\''")}'`;
363
+ }
364
+ /**
365
+ * Resolve a bundled asset by name. Works whether the module runs from `src/`
366
+ * (ts-jest during tests, `__dirname` = src) or `lib/` (a consumer's compiled
367
+ * install, `__dirname` = lib): the asset ships under `src/assets`, so walk up
368
+ * to the package root and read it there. Reading from `lib/assets` would fail
369
+ * for consumers because jsii/tsc does not copy non-TS files into `lib`.
370
+ */
371
+ function resolveAsset(name) {
372
+ const candidates = [
373
+ path.join(__dirname, 'assets', name),
374
+ path.join(__dirname, '..', 'src', 'assets', name),
375
+ ];
376
+ for (const candidate of candidates) {
377
+ if (fs.existsSync(candidate)) {
378
+ return candidate;
379
+ }
380
+ }
381
+ throw new Error(`bundled asset '${name}' not found (looked in: ${candidates.join(', ')})`);
382
+ }
383
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNzLWNyZXctaG9zdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lY3MtY3Jldy1ob3N0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx1Q0FBeUI7QUFDekIsMkNBQTZCO0FBQzdCLDZDQUFpRDtBQUNqRCx5RUFBMkQ7QUFDM0QseURBQTJDO0FBQzNDLHlEQUEyQztBQUMzQyx5REFBMkM7QUFDM0MsMkNBQXVDO0FBQ3ZDLGlEQUE2QztBQUM3QywyREFBOEU7QUFDOUUsNkVBQW1GO0FBRW5GLE1BQU0sWUFBWSxHQUFHLHNCQUFzQixDQUFDO0FBQzVDLE1BQU0sT0FBTyxHQUFHLHNDQUFzQyxDQUFDO0FBRXZELE1BQU0saUJBQWlCLEdBQUcsVUFBVSxDQUFDO0FBQ3JDLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO0FBQzdCLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQztBQUN6QixNQUFNLHNCQUFzQixHQUFHLEVBQUUsQ0FBQztBQUNsQyxNQUFNLHNCQUFzQixHQUFHLEVBQUUsQ0FBQztBQUNsQyxNQUFNLDhCQUE4QixHQUFHLElBQUksQ0FBQztBQUM1QyxNQUFNLDZCQUE2QixHQUFHLElBQUksQ0FBQztBQXlOM0M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFDSCxNQUFhLFdBQVksU0FBUSxzQkFBUzs7SUFDeEMsa0VBQWtFO0lBQ2xELElBQUksQ0FBa0I7SUFDdEMsZ0ZBQWdGO0lBQ2hFLGdCQUFnQixDQUErQjtJQUMvRCxtRUFBbUU7SUFDbkQsZ0JBQWdCLENBQTBCO0lBQzFELHVFQUF1RTtJQUN2RCxJQUFJLENBQVc7SUFDL0IsdURBQXVEO0lBQ3ZDLGlCQUFpQixDQUFvQjtJQUNyRCxrRUFBa0U7SUFDbEQsS0FBSyxDQUFnQjtJQUNyQyxpQ0FBaUM7SUFDakIsUUFBUSxDQUFtQjtJQUMzQyx1RUFBdUU7SUFDdkQsV0FBVyxDQUFtQjtJQUM5Qyw4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QkFBa0IsSUFBSSwyQkFBMkIsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUMxRSxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBTdGFjaywgVGFncywgVG9rZW4gfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBhdXRvc2NhbGluZyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtYXV0b3NjYWxpbmcnO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgZWNzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3MnO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBGYXJnYXRlQ3JldyB9IGZyb20gJy4vZmFyZ2F0ZS1jcmV3JztcbmltcG9ydCB7IEZhcmdhdGVDcHVBcmNoaXRlY3R1cmUsIEZhcmdhdGVDcmV3QmFzZSB9IGZyb20gJy4vZmFyZ2F0ZS1jcmV3LWJhc2UnO1xuaW1wb3J0IHsgQ3Jld0FyY2hpdGVjdHVyZSwgSUNyZXdCYWNrdXBCdWNrZXQgfSBmcm9tICcuL3JlbW90ZS1jcmV3LWluc3RhbmNlLXByb3BzJztcblxuY29uc3QgU1RBQ0tfVEFHX1JFID0gL15bYS16QS1aMC05LV17MSw1MX0kLztcbmNvbnN0IENSRVdfUkUgPSAvXlthLXowLTldKFthLXowLTktXXswLDMwfVthLXowLTldKT8kLztcblxuY29uc3QgREVGQVVMVF9TVEFDS19UQUcgPSAna2lyb2NyZXcnO1xuY29uc3QgREVGQVVMVF9DUkVXX0NPVU5UID0gMTtcbmNvbnN0IE1BWF9DUkVXX0NPVU5UID0gODtcbmNvbnN0IERFRkFVTFRfUk9PVF9WT0xVTUVfR0IgPSA2MDtcbmNvbnN0IERFRkFVTFRfQ1JFV19WT0xVTUVfR0IgPSAyMDtcbmNvbnN0IERFRkFVTFRfTUVNT1JZX1JFU0VSVkFUSU9OX01JQiA9IDEwMjQ7XG5jb25zdCBERUZBVUxUX01FTU9SWV9IQVJEX0xJTUlUX01JQiA9IDIwNDg7XG5cbi8qKlxuICogSG93IGEgcGVyLWNyZXcgZHVyYWJsZSBFQlMgdm9sdW1lIGlzIGV4cG9zZWQgdG8gdGhlIGhvc3QgYW5kIGl0cyBjb250YWluZXIuXG4gKlxuICogVGhlIGRldmljZSBuYW1lIHRoZSBjb25zdHJ1Y3QgYXNrcyBmb3IgKGZvciBleGFtcGxlIGAvZGV2L3NkZmApIGlzIE5PVCB0aGVcbiAqIGtlcm5lbCBkZXZpY2UgbmFtZSBvbiBOaXRyby9HcmF2aXRvbiwgd2hlcmUgZXZlcnkgRUJTIHZvbHVtZSBzdXJmYWNlcyBhcyBhblxuICogdW5wcmVkaWN0YWJsZSBgL2Rldi9udm1lWG4xYC4gVGhlIGJvb3RzdHJhcCB0aGVyZWZvcmUgcmVzb2x2ZXMgZWFjaCB2b2x1bWUgYnlcbiAqIGEgc3RhYmxlIGZpbGVzeXN0ZW0gTEFCRUwsIG5ldmVyIGJ5IHRoZSBkZXZpY2UgcGF0aC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDcmV3RGF0YVZvbHVtZSB7XG4gIC8qKiBUaGUgY3JldyB0aGlzIHZvbHVtZSBiZWxvbmdzIHRvLiAqL1xuICByZWFkb25seSBjcmV3OiBzdHJpbmc7XG4gIC8qKiBUaGUgYmxvY2sgZGV2aWNlIG5hbWUgcmVxdWVzdGVkIGF0IGF0dGFjaCB0aW1lIChhIGhpbnQsIG5vdCB0aGUga2VybmVsIG5hbWUpLiAqL1xuICByZWFkb25seSBkZXZpY2VOYW1lOiBzdHJpbmc7XG4gIC8qKiBUaGUgc3RhYmxlIGZpbGVzeXN0ZW0gbGFiZWwgdGhlIGJvb3RzdHJhcCByZXNvbHZlcyBhbmQgbW91bnRzIGJ5LiAqL1xuICByZWFkb25seSBsYWJlbDogc3RyaW5nO1xuICAvKiogVGhlIGhvc3QgbW91bnQgcGF0aCB0aGUgY29udGFpbmVyIGJpbmQtbW91bnRzIGZvciBgfi8ua2lyby9jcmV3YC4gKi9cbiAgcmVhZG9ubHkgbW91bnRQYXRoOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3Ige0BsaW5rIEVjc0NyZXdIb3N0fS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFY3NDcmV3SG9zdFByb3BzIHtcbiAgLyoqXG4gICAqIFZQQyB0byBydW4gaW4uIFBhc3NlZCBpbiwgbmV2ZXIgY3JlYXRlZCBoZXJlLlxuICAgKlxuICAgKiBUaGUgY29uc3RydWN0IGNvbnN1bWVzIGEgdHdvLXN1Ym5ldCBob3N0LU5BVCB0b3BvbG9neSBpdCBkb2VzIG5vdCBidWlsZDpcbiAgICogb25lIFBVQkxJQyBzdWJuZXQgKGhvc3QgRU5JICsgRWxhc3RpYyBJUCArIElHVyByb3V0ZSkgYW5kIG9uZSBQUklWQVRFXG4gICAqIHN1Ym5ldCAodGFzayBFTklzLCBgMC4wLjAuMC8wYCAtPiB0aGUgaG9zdCBFTkksIG5vIElHVyByb3V0ZSkuIFNlbGVjdCB0aGVtXG4gICAqIHdpdGgge0BsaW5rIGhvc3RTdWJuZXRzfSBhbmQge0BsaW5rIHRhc2tTdWJuZXRzfS5cbiAgICovXG4gIHJlYWRvbmx5IHZwYzogZWMyLklWcGM7XG5cbiAgLyoqXG4gICAqIEFSTiBvZiBhbiBJQU0gcGVybWlzc2lvbnMgYm91bmRhcnkgYXBwbGllZCB0byB0aGUgaG9zdCBpbnN0YW5jZSByb2xlLlxuICAgKlxuICAgKiBUaGUgaG9zdCBydW5zIGEgcHJvbXB0LWluamVjdGFibGUgYWdlbnQgcGVyIGNyZXcsIHNvIGl0cyByb2xlIE1VU1QgY2FycnkgYVxuICAgKiBib3VuZGFyeSB0aGF0IGNhcHMgYmxhc3QgcmFkaXVzLiBSZXF1aXJlZCwgbm90IG9wdGlvbmFsLCBtYXRjaGluZ1xuICAgKiB7QGxpbmsgUmVtb3RlQ3Jld0luc3RhbmNlUHJvcHMucGVybWlzc2lvbnNCb3VuZGFyeUFybn0uIEFueSB2YWxpZCBtYW5hZ2VkLVxuICAgKiBwb2xpY3kgQVJOIGlzIGFjY2VwdGVkIGhlcmUgKHRoaXMgaXMgdGhlIEVDMi9ob3N0IGJvdW5kYXJ5KS5cbiAgICpcbiAgICogVGhlIHBlci1jcmV3IHRhc2svZXhlY3V0aW9uIHJvbGVzIHRha2Uge0BsaW5rIGNyZXdQZXJtaXNzaW9uc0JvdW5kYXJ5QXJufSxcbiAgICogd2hpY2ggaXMgdmFsaWRhdGVkIHNlcGFyYXRlbHkgYWdhaW5zdCB0aGUgYGtpcm9jcmV3LWNyZXctYm91bmRhcnlgIHBhdHRlcm5cbiAgICogdGhlIGNyZXcgcm9sZXMgcmVxdWlyZS5cbiAgICovXG4gIHJlYWRvbmx5IHBlcm1pc3Npb25zQm91bmRhcnlBcm46IHN0cmluZztcblxuICAvKipcbiAgICogQVJOIG9mIHRoZSBwcmUtY3JlYXRlZCBzaGFyZWQgY3JldyBwZXJtaXNzaW9ucyBib3VuZGFyeVxuICAgKiAoYGFybjphd3M6aWFtOjo8YWNjb3VudD46cG9saWN5L2tpcm9jcmV3LWNyZXctYm91bmRhcnlgKSwgYXBwbGllZCB0byBldmVyeVxuICAgKiBwZXItY3JldyB0YXNrIGFuZCBleGVjdXRpb24gcm9sZS5cbiAgICpcbiAgICogU2VwYXJhdGUgZnJvbSB7QGxpbmsgcGVybWlzc2lvbnNCb3VuZGFyeUFybn0gYmVjYXVzZSB0aGUgY3JldyByb2xlcyBlbmZvcmNlXG4gICAqIHRoZSBga2lyb2NyZXctY3Jldy1ib3VuZGFyeWAgcG9saWN5IG5hbWUgKGEgZGlmZmVyZW50IGJvdW5kYXJ5IGZyb20gdGhlXG4gICAqIGhvc3QncyksIGFuZCB2YWxpZGF0aW5nIHRoZW0gdG9nZXRoZXIgd291bGQgZm9yY2Ugb25lIEFSTiB0byBzYXRpc2Z5IHR3b1xuICAgKiBkaXN0aW5jdCBwYXR0ZXJucy4gT3B0aW9uYWwsIG1pcnJvcmluZyB7QGxpbmsgRmFyZ2F0ZUNyZXd9J3MgZGVjbGFyZWRcbiAgICogZGVncmFkZWQgbW9kZTogb21pdCBpdCBvbmx5IHdoZW4gbm8gY3Jldy1ib3VuZGFyeSBjcmVhdG9yIGV4aXN0cyB5ZXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gY3JldyBib3VuZGFyeSAoZGVjbGFyZWQgZGVncmFkZWQgbW9kZTsgc2VlIEZhcmdhdGVDcmV3KVxuICAgKi9cbiAgcmVhZG9ubHkgY3Jld1Blcm1pc3Npb25zQm91bmRhcnlBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEVDMiBpbnN0YW5jZSB0eXBlIGZvciB0aGUgc2luZ2xlIEVDUy1yZWdpc3RlcmVkIGhvc3QuXG4gICAqXG4gICAqIFRoZSB0eXBlIFNUQVlTIGEgc2V0dGFibGUgcHJvcDogdGhlIDU1bWludXRlcyBjb25zdW1lciBwYXNzZXNcbiAgICogYG5ldyBlYzIuSW5zdGFuY2VUeXBlKCdtOWcueGxhcmdlJylgLiBOZXZlciBoYXJkY29kZWQgdG8gb25lIGZhbWlseS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBtN2cuMnhsYXJnZSAoYXJtNjQpIC8gbTdpLjJ4bGFyZ2UgKHg4Nl82NCksIG1hdGNoaW5nXG4gICAqIFJlbW90ZUNyZXdJbnN0YW5jZVxuICAgKi9cbiAgcmVhZG9ubHkgaW5zdGFuY2VUeXBlPzogZWMyLkluc3RhbmNlVHlwZTtcblxuICAvKipcbiAgICogQ1BVIGFyY2hpdGVjdHVyZSBvZiB0aGUgaG9zdCBhbmQgdGhlIGNyZXcgY29udGFpbmVyIGltYWdlcy4gTXVzdCBtYXRjaFxuICAgKiB7QGxpbmsgaW5zdGFuY2VUeXBlfSB3aGVuIHRoYXQgaXMgc2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCBDcmV3QXJjaGl0ZWN0dXJlLkFSTTY0XG4gICAqL1xuICByZWFkb25seSBhcmNoaXRlY3R1cmU/OiBDcmV3QXJjaGl0ZWN0dXJlO1xuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgS2lybyBDcmV3IGluc3RhbmNlcyB0byBob3N0LCBlYWNoIG9uZSBFQ1MgdGFzay9zZXJ2aWNlLlxuICAgKlxuICAgKiBERUZBVUxUIDEg4oCUIGlkZW50aWNhbCB0byB0b2RheSdzIHNpbmdsZS1jcmV3IGJlaGF2aW91ciwgc28gZXhpc3RpbmdcbiAgICogY29uc3VtZXJzIGdhaW4gbm90aGluZyBuZXcuIFRoZSA1NW1pbnV0ZXMgY29uc3VtZXIgcGFzc2VzIDMuIFZhbGlkYXRlZFxuICAgKiAxLi44OiBhd3N2cGMgZ2l2ZXMgZWFjaCB0YXNrIGl0cyBvd24gRU5JLCBhbmQgKGNyZXdDb3VudCArIDEpIEVOSXMgKHRoZVxuICAgKiBob3N0IEVOSSBwbHVzIG9uZSBwZXIgdGFzaykgbXVzdCBmaXQgdGhlIGluc3RhbmNlIHR5cGUncyBFTkkgYnVkZ2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAxXG4gICAqL1xuICByZWFkb25seSBjcmV3Q291bnQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEV4cGxpY2l0IGNyZXcgbmFtZXMuIEVhY2ggbXVzdCBtYXRjaCB0aGUge0BsaW5rIEZhcmdhdGVDcmV3fSByZWdleFxuICAgKiBgXlthLXowLTldKFthLXowLTktXXswLDMwfVthLXowLTldKT8kYDsgdGhlIGxvZyBncm91cCwgcm9sZXMsIGFuZCBzZWNyZXRcbiAgICogbmFtZXNwYWNlIGFyZSBkZXJpdmVkIGZyb20gaXQuIFdoZW4gb21pdHRlZCwgbmFtZXMgYXJlIGdlbmVyYXRlZCBhc1xuICAgKiBgY3Jldy0xYC4uYGNyZXctPGNyZXdDb3VudD5gLiBXaGVuIHNldCwgdGhlIGxpc3QgbGVuZ3RoIG11c3QgZXF1YWxcbiAgICoge0BsaW5rIGNyZXdDb3VudH0uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gY3Jldy0xIC4uIGNyZXctPGNyZXdDb3VudD5cbiAgICovXG4gIHJlYWRvbmx5IGNyZXdzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFN1Ym5ldCBzZWxlY3Rpb24gZm9yIHRoZSBob3N0IEVOSS4gVGhpcyBpcyB0aGUgUFVCTElDIHN1Ym5ldCAoSUdXLXJvdXRlZCxcbiAgICogY2FycmllcyB0aGUgRWxhc3RpYyBJUCksIGJlY2F1c2UgdGhlIGhvc3QgZG9lcyB0aGUgTkFUIGZvciB0aGUgdGFza3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gb25lIHB1YmxpYyBzdWJuZXQgaW4gdGhlIFZQQ1xuICAgKi9cbiAgcmVhZG9ubHkgaG9zdFN1Ym5ldHM/OiBlYzIuU3VibmV0U2VsZWN0aW9uO1xuXG4gIC8qKlxuICAgKiBTdWJuZXQgc2VsZWN0aW9uIGZvciB0aGUgY3JldyB0YXNrIEVOSXMuIFRoaXMgaXMgdGhlIFBSSVZBVEUgc3VibmV0IHdob3NlXG4gICAqIGAwLjAuMC4wLzBgIHJvdXRlIHBvaW50cyBhdCB0aGUgaG9zdCBFTkkgKG5vIElHVyByb3V0ZSkuIFRhc2tzIGdldCBub1xuICAgKiBwdWJsaWMgSVAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIFZQQydzIHByaXZhdGUtd2l0aC1lZ3Jlc3Mgc3VibmV0c1xuICAgKi9cbiAgcmVhZG9ubHkgdGFza1N1Ym5ldHM/OiBlYzIuU3VibmV0U2VsZWN0aW9uO1xuXG4gIC8qKlxuICAgKiBncDMgcm9vdCB2b2x1bWUgc2l6ZSBpbiBHaUIgZm9yIHRoZSBob3N0LiBBbHdheXMgZW5jcnlwdGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCA2MFxuICAgKi9cbiAgcmVhZG9ubHkgcm9vdFZvbHVtZVNpemVHYj86IG51bWJlcjtcblxuICAvKipcbiAgICogUGVyLWNyZXcgZHVyYWJsZSBFQlMgZGF0YSB2b2x1bWUgc2l6ZSBpbiBHaUIuIEFsd2F5cyBlbmNyeXB0ZWQsIGFsd2F5c1xuICAgKiBgZGVsZXRlT25UZXJtaW5hdGlvbjogZmFsc2VgIChhIGNyZXcncyBgfi8ua2lyby9jcmV3YCBsZWFybmluZ3MgbXVzdFxuICAgKiBvdXRsaXZlIGFuIGluc3RhbmNlIHJlcGxhY2VtZW50LCBtYXRjaGluZyB0aGUgQ3Jld0JhY2t1cEJ1Y2tldCBSRVRBSU5cbiAgICogaW50ZW50KS5cbiAgICpcbiAgICogQGRlZmF1bHQgMjBcbiAgICovXG4gIHJlYWRvbmx5IGNyZXdEYXRhVm9sdW1lU2l6ZUdiPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBQZXItY3JldyBFQlMgdm9sdW1lIHR5cGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IGVjMi5FYnNEZXZpY2VWb2x1bWVUeXBlLkdQM1xuICAgKi9cbiAgcmVhZG9ubHkgY3Jld0RhdGFWb2x1bWVUeXBlPzogZWMyLkVic0RldmljZVZvbHVtZVR5cGU7XG5cbiAgLyoqXG4gICAqIFNPRlQgbWVtb3J5IHJlc2VydmF0aW9uIChNaUIpIHBlciBjcmV3IGNvbnRhaW5lci4gRUNTIHVzZXMgaXQgZm9yXG4gICAqIHBsYWNlbWVudDsgYSBjcmV3IG1heSBidXJzdCBhYm92ZSBpdCB3aGVuIHRoZSBob3N0IGhhcyBzcGFyZSBSQU0sIHNvIGlkbGVcbiAgICogY3Jld3MgY29zdCBsaXR0bGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDEwMjRcbiAgICovXG4gIHJlYWRvbmx5IGNyZXdNZW1vcnlSZXNlcnZhdGlvbk1pQj86IG51bWJlcjtcblxuICAvKipcbiAgICogSEFSRCBtZW1vcnkgY2FwIChNaUIpIHBlciBjcmV3IGNvbnRhaW5lci4gQSBjcmV3IGlzIE9PTS1raWxsZWQgYXQgdGhpc1xuICAgKiBjZWlsaW5nLCBzbyBubyBzaW5nbGUgY3JldyBjYW4gY29uc3VtZSB0aGUgd2hvbGUgaG9zdC4gU2V0IHRoZSBTVU0gb2YgaGFyZFxuICAgKiBjYXBzIGF0IG9yIGJlbG93IChwaHlzaWNhbCBSQU0gbWludXMgaG9zdCArIEVDUy1hZ2VudCBoZWFkcm9vbSkgZm9yIGEgaGFyZFxuICAgKiBjcm9zcy1jcmV3IGd1YXJhbnRlZSDigJQgc2VlIHRoZSBob3N0LU9PTSBjYXV0aW9uIGluIHRoZSBSRUFETUUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDIwNDhcbiAgICovXG4gIHJlYWRvbmx5IGNyZXdNZW1vcnlIYXJkTGltaXRNaUI/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIFNPRlQgQ1BVIHNoYXJlcyBwZXIgY3JldyBjb250YWluZXIgKDEwMjQgPSBvbmUgdkNQVSkuIE9taXQgdG9cbiAgICogbGVhdmUgQ1BVIHVuY29uc3RyYWluZWQgKGNyZXdzIHNoYXJlIHRoZSBob3N0IENQVSBmYWlybHkgdW5kZXIgY29udGVudGlvbikuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdW5zZXQgKHNoYXJlZCBDUFUpXG4gICAqL1xuICByZWFkb25seSBjcmV3Q3B1U2hhcmVzPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBBUk4gb2YgdGhlIHByaXZhdGUgRUNSIHJlcG9zaXRvcnkgaG9sZGluZyB0aGUgY3JldyBpbWFnZS4gTGVhdmUgdW5zZXQgd2hlblxuICAgKiB0aGUgaW1hZ2UgaXMgcHVsbGVkIGZyb20gYSBwdWJsaWMgcmVnaXN0cnkuIFdoZW4gc2V0LCBlYWNoIHBlci1jcmV3XG4gICAqIGV4ZWN1dGlvbiByb2xlIGdldHMgYSBwdWxsIGdyYW50IHNjb3BlZCB0byB0aGlzIG9uZSByZXBvc2l0b3J5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHB1YmxpYyByZWdpc3RyeTsgbm8gcHVsbCBncmFudFxuICAgKi9cbiAgcmVhZG9ubHkgZWNyUmVwb3NpdG9yeUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogQ29udGFpbmVyIGltYWdlIHJlZmVyZW5jZSBmb3IgdGhlIGNyZXcgdGFzay4gV2hlbiB7QGxpbmsgZWNyUmVwb3NpdG9yeUFybn1cbiAgICogaXMgc2V0IHRoaXMgaXMgdHlwaWNhbGx5IHRoZSByZXBvIFVSSSB3aXRoIGEgdGFnOyBvdGhlcndpc2UgYSBwdWJsaWNcbiAgICogcmVnaXN0cnkgcmVmZXJlbmNlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAncHVibGljLmVjci5hd3Mva2lyb2NyZXcvY3JldzpsYXRlc3QnXG4gICAqL1xuICByZWFkb25seSBjcmV3SW1hZ2U/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIERheXMgYSBjcmV3J3MgdGFzayBsb2dzIGFyZSBrZXB0LiBPbmUgb2YgdGhlIENsb3VkV2F0Y2ggcmV0ZW50aW9uIHZhbHVlc1xuICAgKiAoc2VlIHtAbGluayBGYXJnYXRlQ3Jld30pLlxuICAgKlxuICAgKiBAZGVmYXVsdCAzMFxuICAgKi9cbiAgcmVhZG9ubHkgbG9nUmV0ZW50aW9uRGF5cz86IG51bWJlcjtcblxuICAvKipcbiAgICogQW4gUzMgYmFja3VwIGJ1Y2tldC4gV2hlbiBzZXQsIGVhY2ggcGVyLWNyZXcgVEFTSyByb2xlIGlzIGdyYW50ZWQgd3JpdGUgc29cbiAgICogdGhlIHJ1bm5pbmcgY29udGFpbmVyIHB1c2hlcyBpdHMgb3duIHNuYXBzaG90cyBvZmYtYm94LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIG9mZi1ib3ggYmFja3VwXG4gICAqL1xuICByZWFkb25seSBiYWNrdXBCdWNrZXQ/OiBJQ3Jld0JhY2t1cEJ1Y2tldDtcblxuICAvKipcbiAgICogRGlzY292ZXJ5IHRhZyB2YWx1ZSB3cml0dGVuIGFzIGBraXJvY3JldzplY3MtaG9zdGAuIE11c3QgbWF0Y2hcbiAgICogYFthLXpBLVowLTktXXsxLDUxfWAuIFRoZSBjbHVzdGVyIGlzIG5hbWVkIGBraXJvY3Jldy1jcmV3LTxzdGFja1RhZz5gLlxuICAgKlxuICAgKiBAZGVmYXVsdCAna2lyb2NyZXcnXG4gICAqL1xuICByZWFkb25seSBzdGFja1RhZz86IHN0cmluZztcbn1cblxuLyoqXG4gKiBPbmUgc2VsZi1wcm92aXNpb25lZCBFQzIgaG9zdCBydW5uaW5nIHRoZSBFQ1MgYWdlbnQsIGhvc3RpbmcgYGNyZXdDb3VudGBcbiAqIEtpcm8gQ3JldyBpbnN0YW5jZXMgYXMgRUNTLW9uLUVDMiBjb250YWluZXIgdGFza3MuXG4gKlxuICogVGhlIGhvc3QgcmVnaXN0ZXJzIHRvIHRoZSB7QGxpbmsgRmFyZ2F0ZUNyZXdCYXNlfSBjbHVzdGVyIGFuZCBkb2VzIHRoZSBOQVRcbiAqIGZvciB0aGUgY3JldyB0YXNrcyBpdHNlbGYsIHNvIHRoZSB0YXNrcyBzdGF5IGZ1bGx5IHByaXZhdGUgd2l0aCBubyBwdWJsaWNcbiAqIElQcyBhbmQgbm8gTkFUIEdhdGV3YXksIGZjay1uYXQsIFZQQyBlbmRwb2ludHMsIG9yIEFMQi4gRWFjaCB0YXNrIHJ1bnMgaW5cbiAqIGF3c3ZwYyBtb2RlIHdpdGggaXRzIG93biBFTkkgYW5kIHByaXZhdGUgVlBDIElQOyBlYWNoIGNyZXcga2VlcHMgaXRzIGR1cmFibGVcbiAqIGB+Ly5raXJvL2NyZXdgIHN0YXRlIG9uIGl0cyBvd24gZW5jcnlwdGVkIEVCUyB2b2x1bWUgdGhhdCBzdXJ2aXZlcyBpbnN0YW5jZVxuICogcmVwbGFjZW1lbnQuXG4gKlxuICogSXNvbGF0aW9uIGlzIGNvbnRhaW5lci1sZXZlbCAoc2hhcmVkIGtlcm5lbCksIGFjY2VwdGVkIGFzIHN1ZmZpY2llbnQ6XG4gKiBHcmF2aXRvbiBOaXRybyBwcm90ZWN0cyB0aGUgYm94IGZyb20gb3RoZXIgQVdTIHRlbmFudHMsIGNvbnRhaW5lcnMgY292ZXJcbiAqIGNyZXctdG8tY3JldyBzZXBhcmF0aW9uLiBTZWUgdGhlIGhvc3QtT09NIGNhdXRpb246IGhhcmQgcGVyLXRhc2sgbWVtb3J5IGNhcHNcbiAqIGJvdW5kIGVhY2ggY3JldydzIGNlaWxpbmcgYnV0IGEgYnVzeSBjcmV3IGNhbiBzdGlsbCBwcmVzc3VyZSBzaWJsaW5ncyB3aGVuXG4gKiB0aGUgc3VtIG9mIGFjdHVhbCB1c2FnZSBleGNlZWRzIHBoeXNpY2FsIFJBTS5cbiAqXG4gKiBgY3Jld0NvdW50YCBkZWZhdWx0cyB0byAxLCBpZGVudGljYWwgdG8gdGhlIHNpbmdsZS1jcmV3IHNoYXBlLCBzbyBhIHBsYWluXG4gKiBpbnN0YW50aWF0aW9uIHdpdGggbm8gbmV3IHByb3BzIGdhaW5zIG5vIGV4dHJhIHJlc291cmNlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIEVjc0NyZXdIb3N0IGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLyoqIFRoZSBzaGFyZWQgRUNTIHNjYWZmb2xkaW5nIChjbHVzdGVyICsgZWdyZXNzLW9ubHkgdGFzayBTRykuICovXG4gIHB1YmxpYyByZWFkb25seSBiYXNlOiBGYXJnYXRlQ3Jld0Jhc2U7XG4gIC8qKiBUaGUgc2l6ZS0xIEF1dG8gU2NhbGluZyBHcm91cCBob2xkaW5nIHRoZSBzaW5nbGUgRUNTLXJlZ2lzdGVyZWQgRUMyIGhvc3QuICovXG4gIHB1YmxpYyByZWFkb25seSBhdXRvU2NhbGluZ0dyb3VwOiBhdXRvc2NhbGluZy5BdXRvU2NhbGluZ0dyb3VwO1xuICAvKiogVGhlIGNhcGFjaXR5IHByb3ZpZGVyIHJlZ2lzdGVyaW5nIHRoZSBob3N0IHdpdGggdGhlIGNsdXN0ZXIuICovXG4gIHB1YmxpYyByZWFkb25seSBjYXBhY2l0eVByb3ZpZGVyOiBlY3MuQXNnQ2FwYWNpdHlQcm92aWRlcjtcbiAgLyoqIFRoZSBob3N0IGluc3RhbmNlJ3MgSUFNIHJvbGUgKGNhcnJpZXMgdGhlIHBlcm1pc3Npb25zIGJvdW5kYXJ5KS4gKi9cbiAgcHVibGljIHJlYWRvbmx5IHJvbGU6IGlhbS5Sb2xlO1xuICAvKiogVGhlIGhvc3QncyBTU00tb25seSBzZWN1cml0eSBncm91cCAobm8gaW5ib3VuZCkuICovXG4gIHB1YmxpYyByZWFkb25seSBob3N0U2VjdXJpdHlHcm91cDogZWMyLlNlY3VyaXR5R3JvdXA7XG4gIC8qKiBUaGUgcGVyLWNyZXcgc2NhZmZvbGRpbmcgKHJvbGVzICsgbG9nIGdyb3VwKSwgb25lIHBlciBjcmV3LiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY3Jld3M6IEZhcmdhdGVDcmV3W107XG4gIC8qKiBUaGUgcGVyLWNyZXcgRUMyIHNlcnZpY2VzLiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc2VydmljZXM6IGVjcy5FYzJTZXJ2aWNlW107XG4gIC8qKiBUaGUgcGVyLWNyZXcgZHVyYWJsZSBkYXRhIHZvbHVtZXMgKGRldmljZS9sYWJlbC9tb3VudCBtZXRhZGF0YSkuICovXG4gIHB1YmxpYyByZWFkb25seSBkYXRhVm9sdW1lczogQ3Jld0RhdGFWb2x1bWVbXTtcbiAgLyoqIFRoZSBkaXNjb3ZlcnkgdGFnIHZhbHVlIHdyaXR0ZW4gYXMgYGtpcm9jcmV3OmVjcy1ob3N0YC4gKi9cbiAgcHVibGljIHJlYWRvbmx5IHN0YWNrVGFnOiBzdHJpbmc7XG4gIC8qKiBUaGUgcmVzb2x2ZWQgY3JldyBuYW1lcy4gKi9cbiAgcHVibGljIHJlYWRvbmx5IGNyZXdOYW1lczogc3RyaW5nW107XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEVjc0NyZXdIb3N0UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3Qgc3RhY2tUYWcgPSBwcm9wcy5zdGFja1RhZyA/PyBERUZBVUxUX1NUQUNLX1RBRztcbiAgICBpZiAoIVNUQUNLX1RBR19SRS50ZXN0KHN0YWNrVGFnKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBzdGFja1RhZyBtdXN0IG1hdGNoICR7U1RBQ0tfVEFHX1JFfSAoZ290ICcke3N0YWNrVGFnfScpYCk7XG4gICAgfVxuICAgIHRoaXMuc3RhY2tUYWcgPSBzdGFja1RhZztcblxuICAgIGNvbnN0IGNyZXdDb3VudCA9IHByb3BzLmNyZXdDb3VudCA/PyBERUZBVUxUX0NSRVdfQ09VTlQ7XG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGNyZXdDb3VudCkgfHwgY3Jld0NvdW50IDwgMSB8fCBjcmV3Q291bnQgPiBNQVhfQ1JFV19DT1VOVCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgY3Jld0NvdW50IG11c3QgYmUgYW4gaW50ZWdlciAxLi4ke01BWF9DUkVXX0NPVU5UfSAoZ290ICR7Y3Jld0NvdW50fSk7IGAgK1xuICAgICAgICAgICdhd3N2cGMgbmVlZHMgKGNyZXdDb3VudCArIDEpIEVOSXMgdG8gZml0IHRoZSBpbnN0YW5jZSB0eXBlJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgY3Jld05hbWVzID0gcHJvcHMuY3Jld3MgPz8gZGVmYXVsdENyZXdOYW1lcyhjcmV3Q291bnQpO1xuICAgIGlmIChjcmV3TmFtZXMubGVuZ3RoICE9PSBjcmV3Q291bnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYGNyZXdzIG11c3QgbGlzdCBleGFjdGx5IGNyZXdDb3VudCAoJHtjcmV3Q291bnR9KSBuYW1lcyAoZ290ICR7Y3Jld05hbWVzLmxlbmd0aH0pYCxcbiAgICAgICk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgY3JldyBvZiBjcmV3TmFtZXMpIHtcbiAgICAgIGlmICghQ1JFV19SRS50ZXN0KGNyZXcpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgY3JldyBuYW1lIG11c3QgbWF0Y2ggJHtDUkVXX1JFfSAoZ290ICcke2NyZXd9Jyk7IGl0IGRlcml2ZXMgdGhlIGAgK1xuICAgICAgICAgICAgJ2xvZyBncm91cCwgcm9sZXMsIGFuZCBzZWNyZXQgbmFtZXNwYWNlJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG5ldyBTZXQoY3Jld05hbWVzKS5zaXplICE9PSBjcmV3TmFtZXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGNyZXcgbmFtZXMgbXVzdCBiZSB1bmlxdWUgKGdvdCAke2NyZXdOYW1lcy5qb2luKCcsICcpfSlgKTtcbiAgICB9XG4gICAgdGhpcy5jcmV3TmFtZXMgPSBjcmV3TmFtZXM7XG5cbiAgICBjb25zdCBhcmNoID0gcHJvcHMuYXJjaGl0ZWN0dXJlID8/IENyZXdBcmNoaXRlY3R1cmUuQVJNNjQ7XG4gICAgY29uc3QgZmFyZ2F0ZUFyY2ggPVxuICAgICAgYXJjaCA9PT0gQ3Jld0FyY2hpdGVjdHVyZS5BUk02NFxuICAgICAgICA/IEZhcmdhdGVDcHVBcmNoaXRlY3R1cmUuQVJNNjRcbiAgICAgICAgOiBGYXJnYXRlQ3B1QXJjaGl0ZWN0dXJlLlg4Nl82NDtcblxuICAgIC8vIC0tLSBTaGFyZWQgRUNTIHNjYWZmb2xkaW5nOiByZXVzZSBGYXJnYXRlQ3Jld0Jhc2UgZm9yIHRoZSBjbHVzdGVyIGFuZCB0aGVcbiAgICAvLyBlZ3Jlc3Mtb25seSB0YXNrIHNlY3VyaXR5IGdyb3VwLCBzbyB0aGVyZSBpcyBvbmUgY29kZSBwYXRoIGZvciB0aGVcbiAgICAvLyBjbHVzdGVyIHRoZSB0YXNrcyByZWdpc3RlciB0by5cbiAgICB0aGlzLmJhc2UgPSBuZXcgRmFyZ2F0ZUNyZXdCYXNlKHRoaXMsICdCYXNlJywge1xuICAgICAgdnBjOiBwcm9wcy52cGMsXG4gICAgICB2cGNTdWJuZXRzOiBwcm9wcy50YXNrU3VibmV0cyxcbiAgICAgIGNwdUFyY2hpdGVjdHVyZTogZmFyZ2F0ZUFyY2gsXG4gICAgICBzdGFja1RhZyxcbiAgICB9KTtcblxuICAgIC8vIC0tLSBIb3N0IGluc3RhbmNlIHJvbGU6IFNTTSBjb3JlICsgcmVxdWlyZWQgYm91bmRhcnksIG1pcnJvcmluZ1xuICAgIC8vIFJlbW90ZUNyZXdJbnN0YW5jZS4gUGx1cyB0aGUgRUNTLWFnZW50IHJlZ2lzdGVyL3RlbGVtZXRyeSBwZXJtaXNzaW9ucyBzb1xuICAgIC8vIHRoaXMgYm94IGNhbiBqb2luIHRoZSBjbHVzdGVyIGFuZCBydW4gdGFza3MuXG4gICAgdGhpcy5yb2xlID0gbmV3IGlhbS5Sb2xlKHRoaXMsICdIb3N0Um9sZScsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdlYzIuYW1hem9uYXdzLmNvbScpLFxuICAgICAgcGVybWlzc2lvbnNCb3VuZGFyeTogaWFtLk1hbmFnZWRQb2xpY3kuZnJvbU1hbmFnZWRQb2xpY3lBcm4oXG4gICAgICAgIHRoaXMsXG4gICAgICAgICdCb3VuZGFyeScsXG4gICAgICAgIHByb3BzLnBlcm1pc3Npb25zQm91bmRhcnlBcm4sXG4gICAgICApLFxuICAgICAgbWFuYWdlZFBvbGljaWVzOiBbXG4gICAgICAgIGlhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZSgnQW1hem9uU1NNTWFuYWdlZEluc3RhbmNlQ29yZScpLFxuICAgICAgICAvLyBUaGUgRUNTIGNvbnRhaW5lci1pbnN0YW5jZSByb2xlOiBSZWdpc3RlckNvbnRhaW5lckluc3RhbmNlLCBQb2xsLFxuICAgICAgICAvLyBTdWJtaXQqLCBhbmQgdGhlIEVDUi9sb2cgYWN0aW9ucyB0aGUgYWdlbnQgbmVlZHMuIFN0YW5kYXJkIGZvciBhblxuICAgICAgICAvLyBFQ1Mtb24tRUMyIGNhcGFjaXR5IGhvc3QuXG4gICAgICAgIGlhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZShcbiAgICAgICAgICAnc2VydmljZS1yb2xlL0FtYXpvbkVDMkNvbnRhaW5lclNlcnZpY2Vmb3JFQzJSb2xlJyxcbiAgICAgICAgKSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyAtLS0gSG9zdCBzZWN1cml0eSBncm91cDogU1NNLW9ubHksIG5vIGluYm91bmQuIEVncmVzcyBvcGVuIGZvciBpbWFnZVxuICAgIC8vIHB1bGxzLCB0aGUgbW9kZWwgZW5kcG9pbnQsIGFuZCBmb3J3YXJkaW5nIHRoZSB0YXNrcycgTkFUZWQgdHJhZmZpYy5cbiAgICB0aGlzLmhvc3RTZWN1cml0eUdyb3VwID0gbmV3IGVjMi5TZWN1cml0eUdyb3VwKHRoaXMsICdIb3N0U2VjdXJpdHlHcm91cCcsIHtcbiAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgZGVzY3JpcHRpb246IGBLaXJvQ3JldyBFQ1MgaG9zdCAke3N0YWNrVGFnfSAtIFNTTS1vbmx5IChubyBpbmJvdW5kKSwgZG9lcyBOQVQgZm9yIGNyZXcgdGFza3NgLFxuICAgICAgYWxsb3dBbGxPdXRib3VuZDogdHJ1ZSxcbiAgICB9KTtcblxuICAgIC8vIC0tLSBBcmNoLWF3YXJlIEVDUy1vcHRpbWl6ZWQgQW1hem9uIExpbnV4IDIwMjMgQU1JICh0aGUgYWdlbnQgaXNcbiAgICAvLyBwcmUtaW5zdGFsbGVkKSwgcmVzb2x2ZWQgdmlhIHRoZSBwdWJsaWMgU1NNIHBhcmFtZXRlciwgbm8gaGFyZGNvZGVkIGlkLlxuICAgIGNvbnN0IGFtaUhhcmR3YXJlVHlwZSA9XG4gICAgICBhcmNoID09PSBDcmV3QXJjaGl0ZWN0dXJlLkFSTTY0XG4gICAgICAgID8gZWNzLkFtaUhhcmR3YXJlVHlwZS5BUk1cbiAgICAgICAgOiBlY3MuQW1pSGFyZHdhcmVUeXBlLlNUQU5EQVJEO1xuICAgIGNvbnN0IG1hY2hpbmVJbWFnZSA9IGVjcy5FY3NPcHRpbWl6ZWRJbWFnZS5hbWF6b25MaW51eDIwMjMoYW1pSGFyZHdhcmVUeXBlKTtcblxuICAgIGNvbnN0IGluc3RhbmNlVHlwZSA9XG4gICAgICBwcm9wcy5pbnN0YW5jZVR5cGUgPz9cbiAgICAgIChhcmNoID09PSBDcmV3QXJjaGl0ZWN0dXJlLkFSTTY0XG4gICAgICAgID8gbmV3IGVjMi5JbnN0YW5jZVR5cGUoJ203Zy4yeGxhcmdlJylcbiAgICAgICAgOiBuZXcgZWMyLkluc3RhbmNlVHlwZSgnbTdpLjJ4bGFyZ2UnKSk7XG5cbiAgICAvLyAtLS0gUGVyLWNyZXcgZHVyYWJsZSBkYXRhIHZvbHVtZXM6IG9uZSBncDMgRUJTIGVhY2gsIGVuY3J5cHRlZCxcbiAgICAvLyBkZWxldGVPblRlcm1pbmF0aW9uOmZhbHNlLCByZXNvbHZlZCBpbiB0aGUgYm9vdHN0cmFwIGJ5IGEgc3RhYmxlIExBQkVMXG4gICAgLy8gKG5ldmVyIC9kZXYvc2RmLCB3aGljaCB0aGUgTml0cm8gTlZNZSBsYXllciByZW5hbWVzKS5cbiAgICBjb25zdCB2b2x1bWVUeXBlID0gcHJvcHMuY3Jld0RhdGFWb2x1bWVUeXBlID8/IGVjMi5FYnNEZXZpY2VWb2x1bWVUeXBlLkdQMztcbiAgICBjb25zdCB2b2x1bWVTaXplID0gcHJvcHMuY3Jld0RhdGFWb2x1bWVTaXplR2IgPz8gREVGQVVMVF9DUkVXX1ZPTFVNRV9HQjtcbiAgICB0aGlzLmRhdGFWb2x1bWVzID0gY3Jld05hbWVzLm1hcCgoY3JldywgaSkgPT4gKHtcbiAgICAgIGNyZXcsXG4gICAgICAvLyBEZXZpY2UgbGV0dGVycyBmLi4gKHNkZiwgc2RnLCAuLi4pIGFyZSBhdHRhY2gtdGltZSBoaW50czsgdGhlIGtlcm5lbFxuICAgICAgLy8gcmVuYW1lcyB0aGVtIG9uIE5pdHJvLCBzbyB0aGUgYm9vdHN0cmFwIGlnbm9yZXMgdGhlbSBhbmQgdXNlcyBsYWJlbC5cbiAgICAgIGRldmljZU5hbWU6IGAvZGV2L3NkJHtTdHJpbmcuZnJvbUNoYXJDb2RlKCdmJy5jaGFyQ29kZUF0KDApICsgaSl9YCxcbiAgICAgIGxhYmVsOiBgY3Jldy0ke2NyZXd9YCxcbiAgICAgIG1vdW50UGF0aDogYC92YXIvbGliL2tpcm9jcmV3LyR7Y3Jld31gLFxuICAgIH0pKTtcblxuICAgIC8vIFRoZSBBU0cgdXNlcyB0aGUgYXV0b3NjYWxpbmcgbW9kdWxlJ3Mgb3duIEJsb2NrRGV2aWNlIHR5cGVzIChkaXN0aW5jdFxuICAgIC8vIGZyb20gZWMyJ3MpLiBUaGUgcHVibGljIGNyZXdEYXRhVm9sdW1lVHlwZSBwcm9wIHN0YXlzIGVjMi10eXBlZCBmb3JcbiAgICAvLyBsaWJyYXJ5IGNvbnNpc3RlbmN5OyB0cmFuc2xhdGUgaXQgYnkgaXRzIHNoYXJlZCBzdHJpbmcgdmFsdWUgaGVyZS5cbiAgICBjb25zdCBhc2dWb2x1bWVUeXBlID0gdm9sdW1lVHlwZSBhcyB1bmtub3duIGFzIGF1dG9zY2FsaW5nLkVic0RldmljZVZvbHVtZVR5cGU7XG4gICAgY29uc3Qgcm9vdEJsb2NrRGV2aWNlOiBhdXRvc2NhbGluZy5CbG9ja0RldmljZSA9IHtcbiAgICAgIGRldmljZU5hbWU6ICcvZGV2L3h2ZGEnLFxuICAgICAgdm9sdW1lOiBhdXRvc2NhbGluZy5CbG9ja0RldmljZVZvbHVtZS5lYnMocHJvcHMucm9vdFZvbHVtZVNpemVHYiA/PyBERUZBVUxUX1JPT1RfVk9MVU1FX0dCLCB7XG4gICAgICAgIHZvbHVtZVR5cGU6IGF1dG9zY2FsaW5nLkVic0RldmljZVZvbHVtZVR5cGUuR1AzLFxuICAgICAgICBlbmNyeXB0ZWQ6IHRydWUsXG4gICAgICAgIGRlbGV0ZU9uVGVybWluYXRpb246IHRydWUsXG4gICAgICB9KSxcbiAgICB9O1xuICAgIGNvbnN0IGNyZXdCbG9ja0RldmljZXM6IGF1dG9zY2FsaW5nLkJsb2NrRGV2aWNlW10gPSB0aGlzLmRhdGFWb2x1bWVzLm1hcCgodikgPT4gKHtcbiAgICAgIGRldmljZU5hbWU6IHYuZGV2aWNlTmFtZSxcbiAgICAgIHZvbHVtZTogYXV0b3NjYWxpbmcuQmxvY2tEZXZpY2VWb2x1bWUuZWJzKHZvbHVtZVNpemUsIHtcbiAgICAgICAgdm9sdW1lVHlwZTogYXNnVm9sdW1lVHlwZSxcbiAgICAgICAgZW5jcnlwdGVkOiB0cnVlLFxuICAgICAgICAvLyBUaGUgd2hvbGUgcG9pbnQ6IGEgY3JldydzIG1lbW9yeSBvdXRsaXZlcyBhbiBpbnN0YW5jZSByZXBsYWNlbWVudC5cbiAgICAgICAgZGVsZXRlT25UZXJtaW5hdGlvbjogZmFsc2UsXG4gICAgICB9KSxcbiAgICB9KSk7XG5cbiAgICAvLyAtLS0gVXNlckRhdGE6IGEgc21hbGwgaGVhZGVyIHRoZSBib290c3RyYXAgYm9keSByZWFkcyAocGVyLWNyZXcgdm9sdW1lXG4gICAgLy8gbGFiZWxzICsgbW91bnQgcGF0aHMsIEVDUyBjbHVzdGVyIG5hbWUpLCB0aGVuIHRoZSBFQ1MtaG9zdCBib290c3RyYXBcbiAgICAvLyBhc3NldCAoaG9zdCBOQVQgKyByZXNvbHZlLWJ5LWxhYmVsIEVCUyBtb3VudCkuIFRoZSBBc2dDYXBhY2l0eVByb3ZpZGVyXG4gICAgLy8gYmVsb3cgQUxTTyBhcHBlbmRzIHRoZSBFQ1MtY2x1c3RlciBqb2luIHRvIHRoaXMgVXNlckRhdGE7IHdyaXRpbmdcbiAgICAvLyBFQ1NfQ0xVU1RFUiBoZXJlIGlzIGEgaGFybWxlc3MgaWRlbXBvdGVudCBiZWx0LWFuZC1icmFjZXMuXG4gICAgY29uc3QgYm9vdHN0cmFwQm9keSA9IGZzLnJlYWRGaWxlU3luYyhyZXNvbHZlQXNzZXQoJ2Vjcy1ob3N0LWJvb3RzdHJhcC5zaCcpLCAndXRmOCcpO1xuICAgIGNvbnN0IHVzZXJEYXRhID0gZWMyLlVzZXJEYXRhLmZvckxpbnV4KCk7XG4gICAgdXNlckRhdGEuYWRkQ29tbWFuZHMoXG4gICAgICAnRUNTX0NMVVNURVI9JyArIHNoZWxsUXVvdGUodGhpcy5iYXNlLmNsdXN0ZXIuY2x1c3Rlck5hbWUpLFxuICAgICAgJ0NSRVdfQ09VTlQ9JyArIFN0cmluZyhjcmV3Q291bnQpLFxuICAgICAgJ0NSRVdfVk9MVU1FX0xBQkVMUz0nICsgc2hlbGxRdW90ZSh0aGlzLmRhdGFWb2x1bWVzLm1hcCgodikgPT4gdi5sYWJlbCkuam9pbignICcpKSxcbiAgICAgICdDUkVXX01PVU5UX1BBVEhTPScgKyBzaGVsbFF1b3RlKHRoaXMuZGF0YVZvbHVtZXMubWFwKCh2KSA9PiB2Lm1vdW50UGF0aCkuam9pbignICcpKSxcbiAgICAgICdleHBvcnQgRUNTX0NMVVNURVIgQ1JFV19DT1VOVCBDUkVXX1ZPTFVNRV9MQUJFTFMgQ1JFV19NT1VOVF9QQVRIUycsXG4gICAgKTtcbiAgICB1c2VyRGF0YS5hZGRDb21tYW5kcyhib290c3RyYXBCb2R5KTtcblxuICAgIC8vIC0tLSBUaGUgc2luZ2xlIEVDUy1yZWdpc3RlcmVkIGhvc3QsIGFzIGEgc2l6ZS0xIEF1dG8gU2NhbGluZyBHcm91cCBiZWhpbmRcbiAgICAvLyBhbiBBc2dDYXBhY2l0eVByb3ZpZGVyLiBBIHNpemUtMSBBU0cgKG1pbj1tYXg9ZGVzaXJlZD0xKSBpcyBzdGlsbCBPTkVcbiAgICAvLyBzZWxmLXByb3Zpc2lvbmVkIEVDMiBob3N0IGFuZCBzdGlsbCBFQ1Mtb24tRUMyIChubyBGYXJnYXRlKTsgdGhlIGNhcGFjaXR5XG4gICAgLy8gcHJvdmlkZXIgaXMgd2hhdCByZWdpc3RlcnMgdGhhdCBjYXBhY2l0eSB3aXRoIHRoZSBjbHVzdGVyIHNvIHRoZSBMMlxuICAgIC8vIEVjMlNlcnZpY2VzIGJlbG93IGNhbiBzY2hlZHVsZSBvbnRvIGl0LiBJTURTdjIgZW5mb3JjZWQgKGFcbiAgICAvLyBwcm9tcHQtaW5qZWN0YWJsZSBhZ2VudCBtdXN0IG5vdCByZWFkIHJvbGUgY3JlZHMgdmlhIElNRFN2MSksIGVuY3J5cHRlZFxuICAgIC8vIGdwMyByb290LCBwbHVzIHRoZSBwZXItY3JldyBkdXJhYmxlIGRhdGEgdm9sdW1lcy5cbiAgICB0aGlzLmF1dG9TY2FsaW5nR3JvdXAgPSBuZXcgYXV0b3NjYWxpbmcuQXV0b1NjYWxpbmdHcm91cCh0aGlzLCAnSG9zdEFzZycsIHtcbiAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgdnBjU3VibmV0czogcHJvcHMuaG9zdFN1Ym5ldHMgPz8geyBzdWJuZXRUeXBlOiBlYzIuU3VibmV0VHlwZS5QVUJMSUMgfSxcbiAgICAgIGluc3RhbmNlVHlwZSxcbiAgICAgIG1hY2hpbmVJbWFnZSxcbiAgICAgIHJvbGU6IHRoaXMucm9sZSxcbiAgICAgIHNlY3VyaXR5R3JvdXA6IHRoaXMuaG9zdFNlY3VyaXR5R3JvdXAsXG4gICAgICB1c2VyRGF0YSxcbiAgICAgIHJlcXVpcmVJbWRzdjI6IHRydWUsXG4gICAgICBtaW5DYXBhY2l0eTogMSxcbiAgICAgIG1heENhcGFjaXR5OiAxLFxuICAgICAgZGVzaXJlZENhcGFjaXR5OiAxLFxuICAgICAgLy8gVGhlIGhvc3QgaXMgaW4gdGhlIFBVQkxJQyBzdWJuZXQgYW5kIGNhcnJpZXMgdGhlIHB1YmxpYyBJUCBzbyBpdFxuICAgICAgLy8gZWdyZXNzZXMgdmlhIHRoZSBJR1cgYW5kIGNhbiBOQVQgdGhlIHRhc2tzLiBUYXNrcyBnZXQgbm9uZS5cbiAgICAgIGFzc29jaWF0ZVB1YmxpY0lwQWRkcmVzczogdHJ1ZSxcbiAgICAgIGJsb2NrRGV2aWNlczogW3Jvb3RCbG9ja0RldmljZSwgLi4uY3Jld0Jsb2NrRGV2aWNlc10sXG4gICAgfSk7XG4gICAgVGFncy5vZih0aGlzLmF1dG9TY2FsaW5nR3JvdXApLmFkZCgnTmFtZScsIGBraXJvY3Jldy1lY3MtaG9zdC0ke3N0YWNrVGFnfWApO1xuXG4gICAgLy8gLS0tIEhvc3QgZG9lcyB0aGUgTkFUOiBpdCBtdXN0IGZvcndhcmQgcGFja2V0cyB0aGF0IGFyZSBuZWl0aGVyIGZyb20gbm9yXG4gICAgLy8gdG8gaXRzIG93biBhZGRyZXNzLCB3aGljaCByZXF1aXJlcyBzb3VyY2UvZGVzdCBjaGVjayBESVNBQkxFRCBvbiB0aGUgaG9zdFxuICAgIC8vIEVOSS4gQ2xvdWRGb3JtYXRpb24gY2Fubm90IHNldCBTb3VyY2VEZXN0Q2hlY2sgb24gYW4gQVNHLWxhdW5jaGVkIGluc3RhbmNlXG4gICAgLy8gZGVjbGFyYXRpdmVseSwgc28gdGhlIGJvb3RzdHJhcCBkaXNhYmxlcyBpdCBvbiB0aGUgaG9zdCBpdHNlbGYgdmlhXG4gICAgLy8gZWMyOk1vZGlmeUluc3RhbmNlQXR0cmlidXRlIChzY29wZWQgYnkgYW4gaW5zdGFuY2UtdGFnIGNvbmRpdGlvbiBzbyB0aGVcbiAgICAvLyBob3N0IGNhbiBvbmx5IGV2ZXIgbW9kaWZ5IGEgS2lyb0NyZXcgRUNTIGhvc3QsIG5vdCBhbiBhcmJpdHJhcnkgaW5zdGFuY2UpLlxuICAgIC8vIFRoZSBib290c3RyYXAgYWxzbyBzZXRzIGlwX2ZvcndhcmQ9MSBhbmQgdGhlIGlwdGFibGVzIE1BU1FVRVJBREUgcnVsZS5cbiAgICB0aGlzLnJvbGUuYWRkVG9Qb2xpY3koXG4gICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFsnZWMyOk1vZGlmeUluc3RhbmNlQXR0cmlidXRlJ10sXG4gICAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICAgIGNvbmRpdGlvbnM6IHtcbiAgICAgICAgICBTdHJpbmdFcXVhbHM6IHsgJ2F3czpSZXNvdXJjZVRhZy9raXJvY3JldzplY3MtaG9zdCc6IHN0YWNrVGFnIH0sXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgLy8gLS0tIFJlZ2lzdGVyIHRoaXMgQVNHJ3MgY2FwYWNpdHkgd2l0aCB0aGUgY2x1c3Rlci4gVGhpcyBpcyB3aGF0IG1ha2VzIHRoZVxuICAgIC8vIGNsdXN0ZXIgaGF2ZSBFYzIgY2FwYWNpdHkgYXMgZmFyIGFzIENESydzIEVjMlNlcnZpY2UgdmFsaWRhdGlvbiBpc1xuICAgIC8vIGNvbmNlcm5lZCwgYW5kIGl0IGFwcGVuZHMgdGhlIEVDUy1jbHVzdGVyIGpvaW4gdG8gdGhlIGhvc3QgVXNlckRhdGEuXG4gICAgdGhpcy5jYXBhY2l0eVByb3ZpZGVyID0gbmV3IGVjcy5Bc2dDYXBhY2l0eVByb3ZpZGVyKHRoaXMsICdIb3N0Q2FwYWNpdHknLCB7XG4gICAgICBhdXRvU2NhbGluZ0dyb3VwOiB0aGlzLmF1dG9TY2FsaW5nR3JvdXAsXG4gICAgICAvLyBUaGUgaW5zdGFuY2VzIGFyZSBsb25nLWxpdmVkIGNyZXcgaG9zdHM7IGRvIG5vdCBsZXQgRUNTIHNjYWxlIHRoZW0gaW5cbiAgICAgIC8vIG9yIHRlcm1pbmF0ZSB0aGVtIGZyb20gdW5kZXIgcnVubmluZyBjcmV3cy5cbiAgICAgIGVuYWJsZU1hbmFnZWRUZXJtaW5hdGlvblByb3RlY3Rpb246IGZhbHNlLFxuICAgIH0pO1xuICAgIHRoaXMuYmFzZS5jbHVzdGVyLmFkZEFzZ0NhcGFjaXR5UHJvdmlkZXIodGhpcy5jYXBhY2l0eVByb3ZpZGVyKTtcblxuICAgIC8vIC0tLSBQZXItY3JldzogRmFyZ2F0ZUNyZXcgc2NhZmZvbGRpbmcgKHJvbGVzICsgbG9nIGdyb3VwKSwgYW4gRUMyIHRhc2tcbiAgICAvLyBkZWZpbml0aW9uIChhd3N2cGMpLCBhIGNvbnRhaW5lciBkZWZpbml0aW9uLCBhbmQgYW4gRWMyU2VydmljZS5cbiAgICB0aGlzLmNyZXdzID0gW107XG4gICAgdGhpcy5zZXJ2aWNlcyA9IFtdO1xuICAgIGNvbnN0IGNyZXdJbWFnZSA9IHByb3BzLmNyZXdJbWFnZSA/PyAncHVibGljLmVjci5hd3Mva2lyb2NyZXcvY3JldzpsYXRlc3QnO1xuICAgIGNvbnN0IG1lbW9yeVJlc2VydmF0aW9uTWlCID1cbiAgICAgIHByb3BzLmNyZXdNZW1vcnlSZXNlcnZhdGlvbk1pQiA/PyBERUZBVUxUX01FTU9SWV9SRVNFUlZBVElPTl9NSUI7XG4gICAgY29uc3QgbWVtb3J5SGFyZExpbWl0TWlCID1cbiAgICAgIHByb3BzLmNyZXdNZW1vcnlIYXJkTGltaXRNaUIgPz8gREVGQVVMVF9NRU1PUllfSEFSRF9MSU1JVF9NSUI7XG4gICAgaWYgKG1lbW9yeVJlc2VydmF0aW9uTWlCID4gbWVtb3J5SGFyZExpbWl0TWlCKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBjcmV3TWVtb3J5UmVzZXJ2YXRpb25NaUIgKCR7bWVtb3J5UmVzZXJ2YXRpb25NaUJ9KSBtdXN0IG5vdCBleGNlZWQgYCArXG4gICAgICAgICAgYGNyZXdNZW1vcnlIYXJkTGltaXRNaUIgKCR7bWVtb3J5SGFyZExpbWl0TWlCfSk6IHRoZSBzb2Z0IHJlc2VydmF0aW9uIGAgK1xuICAgICAgICAgICdjYW5ub3QgYmUgaGlnaGVyIHRoYW4gdGhlIGhhcmQgY2VpbGluZycsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNyZXdOYW1lcy5mb3JFYWNoKChjcmV3LCBpKSA9PiB7XG4gICAgICBjb25zdCBkYXRhVm9sdW1lID0gdGhpcy5kYXRhVm9sdW1lc1tpXTtcbiAgICAgIGNvbnN0IGNyZXdTY2FmZm9sZCA9IG5ldyBGYXJnYXRlQ3Jldyh0aGlzLCBgQ3JldyR7aX1gLCB7XG4gICAgICAgIGNyZXcsXG4gICAgICAgIGxvZ1JldGVudGlvbkRheXM6IHByb3BzLmxvZ1JldGVudGlvbkRheXMsXG4gICAgICAgIHBlcm1pc3Npb25zQm91bmRhcnlBcm46IHByb3BzLmNyZXdQZXJtaXNzaW9uc0JvdW5kYXJ5QXJuLFxuICAgICAgICBlY3JSZXBvc2l0b3J5QXJuOiBwcm9wcy5lY3JSZXBvc2l0b3J5QXJuLFxuICAgICAgICBiYWNrdXBCdWNrZXQ6IHByb3BzLmJhY2t1cEJ1Y2tldCxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jcmV3cy5wdXNoKGNyZXdTY2FmZm9sZCk7XG5cbiAgICAgIGNvbnN0IHRhc2tEZWYgPSBuZXcgZWNzLkVjMlRhc2tEZWZpbml0aW9uKHRoaXMsIGBUYXNrRGVmJHtpfWAsIHtcbiAgICAgICAgLy8gYXdzdnBjOiBlYWNoIHRhc2sgZ2V0cyBpdHMgb3duIEVOSSArIHByaXZhdGUgVlBDIElQLlxuICAgICAgICBuZXR3b3JrTW9kZTogZWNzLk5ldHdvcmtNb2RlLkFXU19WUEMsXG4gICAgICAgIHRhc2tSb2xlOiBjcmV3U2NhZmZvbGQudGFza1JvbGUsXG4gICAgICAgIGV4ZWN1dGlvblJvbGU6IGNyZXdTY2FmZm9sZC5leGVjdXRpb25Sb2xlLFxuICAgICAgICAvLyBObyBydW50aW1lUGxhdGZvcm06IGFuIEVDMiB0YXNrJ3MgYXJjaGl0ZWN0dXJlIGlzIHRoYXQgb2YgdGhlIGhvc3QgaXRcbiAgICAgICAgLy8gbGFuZHMgb24gKHRoZSBhcm02NCBFQ1Mtb3B0aW1pemVkIEFNSSBoZXJlKSwgbm90IGEgdGFzay1kZWYgZmllbGRcbiAgICAgICAgLy8gKHRoYXQgaXMgRmFyZ2F0ZS1vbmx5KS5cbiAgICAgICAgLy8gQSBob3N0IHZvbHVtZSBtYXBwaW5nIHRoZSBjcmV3J3MgbW91bnRlZCBFQlMgcGF0aCBzbyB+Ly5raXJvL2NyZXcgaXNcbiAgICAgICAgLy8gZHVyYWJsZSBhY3Jvc3MgdGFzay9pbnN0YW5jZSByZXBsYWNlbWVudC5cbiAgICAgICAgdm9sdW1lczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IGBjcmV3LWRhdGEtJHtjcmV3fWAsXG4gICAgICAgICAgICBob3N0OiB7IHNvdXJjZVBhdGg6IGRhdGFWb2x1bWUubW91bnRQYXRoIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBjb250YWluZXIgPSB0YXNrRGVmLmFkZENvbnRhaW5lcihgQ3JldyR7aX1Db250YWluZXJgLCB7XG4gICAgICAgIGltYWdlOiBlY3MuQ29udGFpbmVySW1hZ2UuZnJvbVJlZ2lzdHJ5KGNyZXdJbWFnZSksXG4gICAgICAgIC8vIFNPRlQgcmVzZXJ2YXRpb24gZm9yIHNjaGVkdWxpbmc7IGlkbGUgY3Jld3MgY29zdCBsaXR0bGUuXG4gICAgICAgIG1lbW9yeVJlc2VydmF0aW9uTWlCLFxuICAgICAgICAvLyBIQVJEIGNhcCBzbyBhIHJ1bmF3YXkgY3JldyBjYW5ub3QgZXhjZWVkIGl0cyBjZWlsaW5nIChob3N0LU9PTVxuICAgICAgICAvLyBibGFzdC1yYWRpdXMgY2F1dGlvbiBpbiB0aGUgUkVBRE1FKS5cbiAgICAgICAgbWVtb3J5TGltaXRNaUI6IG1lbW9yeUhhcmRMaW1pdE1pQixcbiAgICAgICAgLy8gT3B0aW9uYWwgc29mdCBDUFUgc2hhcmVzOyB1bnNldCA9PiBzaGFyZWQgQ1BVIHVuZGVyIGNvbnRlbnRpb24uXG4gICAgICAgIGNwdTogcHJvcHMuY3Jld0NwdVNoYXJlcyxcbiAgICAgICAgbG9nZ2luZzogZWNzLkxvZ0RyaXZlci5hd3NMb2dzKHtcbiAgICAgICAgICBzdHJlYW1QcmVmaXg6IGNyZXcsXG4gICAgICAgICAgbG9nR3JvdXA6IGNyZXdTY2FmZm9sZC5sb2dHcm91cCxcbiAgICAgICAgfSksXG4gICAgICB9KTtcbiAgICAgIGNvbnRhaW5lci5hZGRNb3VudFBvaW50cyh7XG4gICAgICAgIGNvbnRhaW5lclBhdGg6ICcvaG9tZS9raXJvY3Jldy8ua2lyby9jcmV3JyxcbiAgICAgICAgc291cmNlVm9sdW1lOiBgY3Jldy1kYXRhLSR7Y3Jld31gLFxuICAgICAgICByZWFkT25seTogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgc2VydmljZSA9IG5ldyBlY3MuRWMyU2VydmljZSh0aGlzLCBgU2VydmljZSR7aX1gLCB7XG4gICAgICAgIGNsdXN0ZXI6IHRoaXMuYmFzZS5jbHVzdGVyLFxuICAgICAgICB0YXNrRGVmaW5pdGlvbjogdGFza0RlZixcbiAgICAgICAgZGVzaXJlZENvdW50OiAxLFxuICAgICAgICAvLyBhd3N2cGMgcGxhY2VtZW50OiB0aGUgUFJJVkFURSB0YXNrIHN1Ym5ldCwgdGhlIGVncmVzcy1vbmx5IHRhc2sgU0csXG4gICAgICAgIC8vIG5vIHB1YmxpYyBJUCAodGFza3MgYXJlIGZ1bGx5IHByaXZhdGU7IHRoZSBob3N0IE5BVHMgdGhlaXIgZWdyZXNzKS5cbiAgICAgICAgc2VjdXJpdHlHcm91cHM6IFt0aGlzLmJhc2Uuc2VjdXJpdHlHcm91cF0sXG4gICAgICAgIHZwY1N1Ym5ldHM6IHByb3BzLnRhc2tTdWJuZXRzID8/IHtcbiAgICAgICAgICBzdWJuZXRUeXBlOiBlYzIuU3VibmV0VHlwZS5QUklWQVRFX1dJVEhfRUdSRVNTLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICAvLyBUaGUgc2VydmljZSBkZXBlbmRzIG9uIHRoZSBob3N0IGNhcGFjaXR5IGJlaW5nIHJlZ2lzdGVyZWQuXG4gICAgICBzZXJ2aWNlLm5vZGUuYWRkRGVwZW5kZW5jeSh0aGlzLmNhcGFjaXR5UHJvdmlkZXIpO1xuICAgICAgdGhpcy5zZXJ2aWNlcy5wdXNoKHNlcnZpY2UpO1xuICAgIH0pO1xuXG4gICAgLy8gVGFnIHRoZSBBU0cgKHRhZ3MgcHJvcGFnYXRlIHRvIGxhdW5jaGVkIGluc3RhbmNlcyBieSBkZWZhdWx0KSwgc28gdGhlXG4gICAgLy8ga2lyb2NyZXc6ZWNzLWhvc3QgdGFnIHRoZSBNb2RpZnlJbnN0YW5jZUF0dHJpYnV0ZSBjb25kaXRpb24ga2V5cyBvZmYgaXNcbiAgICAvLyBwcmVzZW50IG9uIHRoZSBob3N0LCBhbmQgdGhlIFNHLlxuICAgIGZvciAoY29uc3QgdGFnZ2FibGUgb2YgW3RoaXMuYXV0b1NjYWxpbmdHcm91cCwgdGhpcy5ob3N0U2VjdXJpdHlHcm91cF0pIHtcbiAgICAgIFRhZ3Mub2YodGFnZ2FibGUpLmFkZCgna2lyb2NyZXc6bWFuYWdlZCcsICd0cnVlJyk7XG4gICAgICBUYWdzLm9mKHRhZ2dhYmxlKS5hZGQoJ2tpcm9jcmV3OmVjcy1ob3N0Jywgc3RhY2tUYWcpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBUaGUgcmVnaW9uIHRoZSBob3N0IHJ1bnMgaW4gKHJlYWQgZnJvbSB0aGUgc3RhY2sgZW52LCBuZXZlciBhIHByb3ApLiAqL1xuICBwdWJsaWMgZ2V0IHJlZ2lvbigpOiBzdHJpbmcge1xuICAgIHJldHVybiBTdGFjay5vZih0aGlzKS5yZWdpb247XG4gIH1cbn1cblxuLyoqIEdlbmVyYXRlIGRlZmF1bHQgY3JldyBuYW1lcyBjcmV3LTEgLi4gY3Jldy08Y291bnQ+LiAqL1xuZnVuY3Rpb24gZGVmYXVsdENyZXdOYW1lcyhjb3VudDogbnVtYmVyKTogc3RyaW5nW10ge1xuICBjb25zdCBuYW1lczogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDE7IGkgPD0gY291bnQ7IGkrKykge1xuICAgIG5hbWVzLnB1c2goYGNyZXctJHtpfWApO1xuICB9XG4gIHJldHVybiBuYW1lcztcbn1cblxuLyoqIFNpbmdsZS1xdW90ZSBhIGxpdGVyYWwgZm9yIHNhZmUgZW1iZWRkaW5nOyBwYXNzIENESyB0b2tlbnMgdGhyb3VnaC4gKi9cbmZ1bmN0aW9uIHNoZWxsUXVvdGUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiBgJyR7dmFsdWUucmVwbGFjZSgvJy9nLCBcIidcXFxcJydcIil9J2A7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhIGJ1bmRsZWQgYXNzZXQgYnkgbmFtZS4gV29ya3Mgd2hldGhlciB0aGUgbW9kdWxlIHJ1bnMgZnJvbSBgc3JjL2BcbiAqICh0cy1qZXN0IGR1cmluZyB0ZXN0cywgYF9fZGlybmFtZWAgPSBzcmMpIG9yIGBsaWIvYCAoYSBjb25zdW1lcidzIGNvbXBpbGVkXG4gKiBpbnN0YWxsLCBgX19kaXJuYW1lYCA9IGxpYik6IHRoZSBhc3NldCBzaGlwcyB1bmRlciBgc3JjL2Fzc2V0c2AsIHNvIHdhbGsgdXBcbiAqIHRvIHRoZSBwYWNrYWdlIHJvb3QgYW5kIHJlYWQgaXQgdGhlcmUuIFJlYWRpbmcgZnJvbSBgbGliL2Fzc2V0c2Agd291bGQgZmFpbFxuICogZm9yIGNvbnN1bWVycyBiZWNhdXNlIGpzaWkvdHNjIGRvZXMgbm90IGNvcHkgbm9uLVRTIGZpbGVzIGludG8gYGxpYmAuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVBc3NldChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBjYW5kaWRhdGVzID0gW1xuICAgIHBhdGguam9pbihfX2Rpcm5hbWUsICdhc3NldHMnLCBuYW1lKSxcbiAgICBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nLCAnc3JjJywgJ2Fzc2V0cycsIG5hbWUpLFxuICBdO1xuICBmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiBjYW5kaWRhdGVzKSB7XG4gICAgaWYgKGZzLmV4aXN0c1N5bmMoY2FuZGlkYXRlKSkge1xuICAgICAgcmV0dXJuIGNhbmRpZGF0ZTtcbiAgICB9XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKFxuICAgIGBidW5kbGVkIGFzc2V0ICcke25hbWV9JyBub3QgZm91bmQgKGxvb2tlZCBpbjogJHtjYW5kaWRhdGVzLmpvaW4oJywgJyl9KWAsXG4gICk7XG59XG4iXX0=
@@ -60,7 +60,7 @@ var FargateCpuArchitecture;
60
60
  * Port of the upstream `kirocrew-fargate-base` CloudFormation template.
61
61
  */
62
62
  class FargateCrewBase extends constructs_1.Construct {
63
- static [JSII_RTTI_SYMBOL_1] = { fqn: "@raindancers/raindancers-crew.FargateCrewBase", version: "0.0.0" };
63
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "@raindancers/raindancers-crew.FargateCrewBase", version: "0.0.2" };
64
64
  /** The ECS cluster crew tasks run on. */
65
65
  cluster;
66
66
  /** The egress-only task security group (no inbound). */
@@ -68,7 +68,7 @@ const ALLOWED_RETENTION_DAYS = [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365];
68
68
  * roles are not assumable on behalf of an unrelated stack's task.
69
69
  */
70
70
  class FargateCrew extends constructs_1.Construct {
71
- static [JSII_RTTI_SYMBOL_1] = { fqn: "@raindancers/raindancers-crew.FargateCrew", version: "0.0.0" };
71
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "@raindancers/raindancers-crew.FargateCrew", version: "0.0.2" };
72
72
  /** Role ECS assumes BEFORE the container starts (secret fetch + log stream). */
73
73
  executionRole;
74
74
  /** Identity the RUNNING container carries. Created with no policies. */
package/lib/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export * from './remote-crew-instance-props';
3
3
  export * from './fargate-crew-base';
4
4
  export * from './fargate-crew';
5
5
  export * from './crew-backup-bucket';
6
+ export * from './ecs-crew-host';
7
+ export * from './crew-webhook-ingress';
package/lib/index.js CHANGED
@@ -19,4 +19,6 @@ __exportStar(require("./remote-crew-instance-props"), exports);
19
19
  __exportStar(require("./fargate-crew-base"), exports);
20
20
  __exportStar(require("./fargate-crew"), exports);
21
21
  __exportStar(require("./crew-backup-bucket"), exports);
22
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHlEQUF1QztBQUN2QywrREFBNkM7QUFDN0Msc0RBQW9DO0FBQ3BDLGlEQUErQjtBQUMvQix1REFBcUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL3JlbW90ZS1jcmV3LWluc3RhbmNlJztcbmV4cG9ydCAqIGZyb20gJy4vcmVtb3RlLWNyZXctaW5zdGFuY2UtcHJvcHMnO1xuZXhwb3J0ICogZnJvbSAnLi9mYXJnYXRlLWNyZXctYmFzZSc7XG5leHBvcnQgKiBmcm9tICcuL2ZhcmdhdGUtY3Jldyc7XG5leHBvcnQgKiBmcm9tICcuL2NyZXctYmFja3VwLWJ1Y2tldCc7XG4iXX0=
22
+ __exportStar(require("./ecs-crew-host"), exports);
23
+ __exportStar(require("./crew-webhook-ingress"), exports);
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHlEQUF1QztBQUN2QywrREFBNkM7QUFDN0Msc0RBQW9DO0FBQ3BDLGlEQUErQjtBQUMvQix1REFBcUM7QUFDckMsa0RBQWdDO0FBQ2hDLHlEQUF1QyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vcmVtb3RlLWNyZXctaW5zdGFuY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9yZW1vdGUtY3Jldy1pbnN0YW5jZS1wcm9wcyc7XG5leHBvcnQgKiBmcm9tICcuL2ZhcmdhdGUtY3Jldy1iYXNlJztcbmV4cG9ydCAqIGZyb20gJy4vZmFyZ2F0ZS1jcmV3JztcbmV4cG9ydCAqIGZyb20gJy4vY3Jldy1iYWNrdXAtYnVja2V0JztcbmV4cG9ydCAqIGZyb20gJy4vZWNzLWNyZXctaG9zdCc7XG5leHBvcnQgKiBmcm9tICcuL2NyZXctd2ViaG9vay1pbmdyZXNzJztcbiJdfQ==
@@ -68,7 +68,7 @@ const DEFAULT_TIMEOUT_MIN = 25;
68
68
  * diagnostics.
69
69
  */
70
70
  class RemoteCrewInstance extends constructs_1.Construct {
71
- static [JSII_RTTI_SYMBOL_1] = { fqn: "@raindancers/raindancers-crew.RemoteCrewInstance", version: "0.0.0" };
71
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "@raindancers/raindancers-crew.RemoteCrewInstance", version: "0.0.2" };
72
72
  /** The EC2 instance (SSM target). */
73
73
  instance;
74
74
  /** The instance's IAM role (carries the permissions boundary). */
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "post-compile": "projen post-compile",
22
22
  "post-upgrade": "projen post-upgrade",
23
23
  "pre-compile": "projen pre-compile",
24
- "release": "projen release",
24
+ "release:feat/remote-crew-instance": "projen release:feat/remote-crew-instance",
25
25
  "test": "projen test",
26
26
  "test:watch": "projen test:watch",
27
27
  "unbump": "projen unbump",
@@ -81,7 +81,7 @@
81
81
  "publishConfig": {
82
82
  "access": "public"
83
83
  },
84
- "version": "0.0.0",
84
+ "version": "0.0.2",
85
85
  "jest": {
86
86
  "coverageProvider": "v8",
87
87
  "testMatch": [