@odigos/aws-cdk 0.0.13 → 0.0.14

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/lib/fargate.js ADDED
@@ -0,0 +1,400 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.OdigosFargateInstrumentation = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
7
+ const ecs = require("aws-cdk-lib/aws-ecs");
8
+ const constructs_1 = require("constructs");
9
+ const collector_config_1 = require("./collector-config");
10
+ const fargate_1 = require("./generated/fargate");
11
+ const layers_1 = require("./generated/layers");
12
+ const fargate_recipes_1 = require("./fargate-recipes");
13
+ /** Service name reported on every span, metric and log record. */
14
+ const ENV_SERVICE_NAME = 'OTEL_SERVICE_NAME';
15
+ /** Resource attributes added to every record: cloud provider, platform and region. */
16
+ const ENV_RESOURCE_ATTRIBUTES = 'OTEL_RESOURCE_ATTRIBUTES';
17
+ /** Where the agent exports OTLP. On Fargate this is the real destination, not a localhost collector. */
18
+ const ENV_OTLP_ENDPOINT = 'OTEL_EXPORTER_OTLP_ENDPOINT';
19
+ /** The transport for the endpoint above. The two are one decision. */
20
+ const ENV_OTLP_PROTOCOL = 'OTEL_EXPORTER_OTLP_PROTOCOL';
21
+ /** Per-request headers, in practice the destination's credential. */
22
+ const ENV_OTLP_HEADERS = 'OTEL_EXPORTER_OTLP_HEADERS';
23
+ /** Raises agent verbosity into the container's log stream. */
24
+ const ENV_OTEL_LOG_LEVEL = 'OTEL_LOG_LEVEL';
25
+ /** The three per-signal exporter switches. */
26
+ const ENV_TRACES_EXPORTER = 'OTEL_TRACES_EXPORTER';
27
+ const ENV_METRICS_EXPORTER = 'OTEL_METRICS_EXPORTER';
28
+ const ENV_LOGS_EXPORTER = 'OTEL_LOGS_EXPORTER';
29
+ /** Value a supported signal's exporter is set to. */
30
+ const EXPORTER_OTLP = 'otlp';
31
+ /**
32
+ * Schema version of the marker payload. Must match `api.IaCMarkerVersion` in the connector — it is what
33
+ * tells the connector how to read the rest of the object, so a bumped version there is a change here.
34
+ */
35
+ const MARKER_VERSION = 1;
36
+ /**
37
+ * `ODIGOS_IAC` — the marker recording that this container was instrumented by Odigos IaC tooling, by
38
+ * which package version, and for which language.
39
+ *
40
+ * It is PER CONTAINER, and it is the only thing that makes Odigos report a container as instrumented
41
+ * rather than "awaiting your deployment" — however completely the rest of the wiring is applied. A task
42
+ * definition holding two applications needs it on both.
43
+ *
44
+ * The `lang` field is the load-bearing one here (where Lambda's is `layer`). The connector's conformance
45
+ * check reconstructs the container's expected activation environment from the recorded language, so it is
46
+ * what makes "is this container correctly instrumented" answerable at all — and it is cross-checked
47
+ * against the language the connector resolves independently, which is how an image swapped underneath the
48
+ * instrumentation is caught.
49
+ *
50
+ * It is NOT `ODIGOS_MANAGED`, and this construct never writes that one. That is the connector's own
51
+ * record of a mutation IT performed, whose payload is the snapshot it restores from on rollback. A CDK
52
+ * stack has no such snapshot to offer, because nothing was mutated — the container definition below IS
53
+ * the container's definition. Writing it by hand would claim a rollback nobody recorded, and the
54
+ * connector would then judge the container against values that do not exist.
55
+ */
56
+ const ENV_IAC_MARKER = 'ODIGOS_IAC';
57
+ /** Construct id of the staging container inside the task definition's scope. */
58
+ const SIDECAR_CONSTRUCT_ID = 'OdigosAgent';
59
+ /**
60
+ * Memory reservation for the staging container on an EC2-only task definition, where ECS requires every
61
+ * container to declare its own if the task does not. Never set on a Fargate task definition — see the
62
+ * call site.
63
+ */
64
+ const SIDECAR_EC2_MEMORY_MIB = 64;
65
+ /**
66
+ * Instruments ECS Fargate containers with the Odigos OpenTelemetry agents.
67
+ *
68
+ * ```ts
69
+ * const odigos = new OdigosFargateInstrumentation(this, 'Odigos', {
70
+ * destination: { httpEndpoint: 'https://otlp.example.com:4318' },
71
+ * });
72
+ * odigos.instrument({
73
+ * container: apiContainer,
74
+ * language: OdigosFargateLanguage.JAVA,
75
+ * service: apiService,
76
+ * });
77
+ * ```
78
+ *
79
+ * ## What it does to the task definition
80
+ *
81
+ * Four moves, which are one mechanism and only work together — the ECS adaptation of the Odikos
82
+ * init-container mount method:
83
+ *
84
+ * 1. a bare-name task volume (`odigos-agent`), which on Fargate is an ephemeral-storage bind mount
85
+ * scoped to the task;
86
+ * 2. a NON-ESSENTIAL `odigos-agent` container that copies the language agents out of the agents bundle
87
+ * into that volume and exits 0;
88
+ * 3. the volume mounted read-only at `/var/odigos` in each instrumented container, which depends on the
89
+ * staging container with condition `SUCCESS` — only valid against a non-essential container, which is
90
+ * why (2) is non-essential;
91
+ * 4. the language's activation environment, the OTLP export environment, and the `ODIGOS_IAC` marker on
92
+ * each instrumented container.
93
+ *
94
+ * There is ONE staging container per task definition however many languages the task holds; its command
95
+ * is the union of every instrumented container's agent directories, and it is built lazily so containers
96
+ * instrumented later are included.
97
+ *
98
+ * ## Where the telemetry goes
99
+ *
100
+ * Straight to your destination, from inside the application process. This is the substantive difference
101
+ * from Lambda: there is no collector in the task to hand a batch to, so a slow or unreachable destination
102
+ * is felt by the application's own exporter rather than absorbed after a response has been returned.
103
+ *
104
+ * ## What it deliberately does NOT do
105
+ *
106
+ * There is no aspect that sweeps a scope, as there is for Lambda. An aspect there works because a
107
+ * function DECLARES its runtime; a container declares an image, and a language guessed from an image name
108
+ * would silently mis-instrument the ones it got wrong — staging a Java agent into a Python container
109
+ * leaves it uninstrumented, and a `JAVA_TOOL_OPTIONS` on a JVM-less image is simply ignored, so nothing
110
+ * fails loudly enough to notice.
111
+ *
112
+ * ## Do not also instrument these services with the connector
113
+ *
114
+ * The connector instruments live services by registering a new task-definition revision and updating the
115
+ * service to it, reconciling to its own desired state on every pass. A service instrumented here and also
116
+ * enabled as a connector source ends up owned by both: each `cdk deploy` reasserts the stack's
117
+ * definition, each reconcile reasserts the connector's, and every round trip registers a revision and
118
+ * rolls the service. Choose one per service.
119
+ */
120
+ class OdigosFargateInstrumentation extends constructs_1.Construct {
121
+ constructor(scope, id, props) {
122
+ super(scope, id);
123
+ this.taskDefinitions = new Map();
124
+ this.instrumented = new Set();
125
+ this.options = props;
126
+ const image = props.agentsImage ?? fargate_1.FARGATE_AGENTS_IMAGE;
127
+ if (!image) {
128
+ // Empty only in a checkout built before the first release. Failing here is the point: the
129
+ // alternative is a task definition whose staging container names a tag that does not exist, which
130
+ // surfaces as a task that will not start, at deploy time, in a place that says nothing about why.
131
+ throw new Error('Odigos: this build of @odigos/aws-cdk has no Fargate agents image baked in — it was built ' +
132
+ 'before the first release. Use a released version of the package, or pass `agentsImage` ' +
133
+ 'explicitly.');
134
+ }
135
+ this.agentsImage = image;
136
+ for (const target of props.targets ?? []) {
137
+ this.instrument(target);
138
+ }
139
+ }
140
+ /**
141
+ * Instruments one container. Idempotent — instrumenting the same container twice is a no-op rather than
142
+ * a doubled loader value.
143
+ */
144
+ instrument(target) {
145
+ const container = target.container;
146
+ const key = container.node.path;
147
+ if (this.instrumented.has(key)) {
148
+ return;
149
+ }
150
+ const taskDefinition = container.taskDefinition;
151
+ const recipe = (0, fargate_recipes_1.recipeFor)(target.language, target.runtimeVersion);
152
+ const serviceName = this.resolveServiceName(target);
153
+ this.checkTaskDefinition(taskDefinition, container);
154
+ this.instrumented.add(key);
155
+ const state = this.taskDefinitionState(taskDefinition);
156
+ for (const dir of recipe.agentDirs) {
157
+ state.agentDirs.add(dir);
158
+ }
159
+ // Read-only: the agents are only read here, and the staging container owns the writes.
160
+ container.addMountPoints({
161
+ sourceVolume: fargate_1.FARGATE_VOLUME_NAME,
162
+ containerPath: fargate_1.FARGATE_AGENTS_DIR,
163
+ readOnly: true,
164
+ });
165
+ // SUCCESS, not START: the agent files have to be on disk before the application process begins, and
166
+ // the staging container exits as soon as they are.
167
+ container.addContainerDependencies({
168
+ container: state.sidecar,
169
+ condition: ecs.ContainerDependencyCondition.SUCCESS,
170
+ });
171
+ for (const [name, value] of Object.entries(this.environmentFor(target, recipe, serviceName))) {
172
+ container.addEnvironment(name, value);
173
+ }
174
+ }
175
+ /** Instruments every target in the list. */
176
+ instrumentAll(targets) {
177
+ for (const target of targets) {
178
+ this.instrument(target);
179
+ }
180
+ }
181
+ /**
182
+ * The task definition's staging container and volume, created once and shared by every container in it.
183
+ *
184
+ * The command is a lazy list rather than a literal because the union it renders is not known until
185
+ * synthesis: a task definition holding a Java and a Python application is instrumented by two
186
+ * `instrument()` calls, and the single staging container has to stage both. The connector compares this
187
+ * command against exactly that union, so a stale one is reported as drift on the whole task definition
188
+ * and leaves one of the containers with no agent on disk.
189
+ */
190
+ taskDefinitionState(taskDefinition) {
191
+ const key = taskDefinition.node.path;
192
+ const existing = this.taskDefinitions.get(key);
193
+ if (existing) {
194
+ return existing;
195
+ }
196
+ // A bare-name volume — no host, docker or EFS configuration — is a Fargate ephemeral-storage bind
197
+ // mount scoped to the task, which is exactly the shared staging area needed and the only kind Fargate
198
+ // offers (there is no tmpfs).
199
+ taskDefinition.addVolume({ name: fargate_1.FARGATE_VOLUME_NAME });
200
+ const agentDirs = new Set();
201
+ const sidecar = taskDefinition.addContainer(SIDECAR_CONSTRUCT_ID, {
202
+ containerName: fargate_1.FARGATE_SIDECAR_CONTAINER_NAME,
203
+ image: ecs.ContainerImage.fromRegistry(this.agentsImage),
204
+ // Non-essential is not a preference: it is what makes the SUCCESS dependency above legal, and it is
205
+ // what stops a copier that has finished its job from failing the whole task by exiting.
206
+ essential: false,
207
+ command: aws_cdk_lib_1.Lazy.list({ produce: () => (0, fargate_recipes_1.sidecarCommand)([...agentDirs]) }),
208
+ // Fargate allocates memory at the task level, so the staging container declares none there — which
209
+ // keeps the rendered container byte-identical to what the connector writes. An EC2-only task
210
+ // definition without task-level memory requires every container to declare its own, so one is set
211
+ // for that case alone. A soft reservation, and generous: the container is busybox running `cp`.
212
+ memoryReservationMiB: taskDefinition.isFargateCompatible ? undefined : SIDECAR_EC2_MEMORY_MIB,
213
+ });
214
+ // Writable here — this is the container that puts the files there. `readOnly` is required by CDK's
215
+ // MountPoint struct where the connector simply omits it; false is what an omitted value means, and the
216
+ // connector's task-level check compares the staging container's image, essentiality and command, not
217
+ // its mounts, so spelling out the default is not drift.
218
+ sidecar.addMountPoints({
219
+ sourceVolume: fargate_1.FARGATE_VOLUME_NAME,
220
+ containerPath: fargate_1.FARGATE_AGENTS_DIR,
221
+ readOnly: false,
222
+ });
223
+ // Registered here, with the staging container, so it is added once per task definition however many
224
+ // containers are instrumented in it — and counted at synth, so containers added after this call are
225
+ // included. AWS rejects a RegisterTaskDefinition over the limit, which would otherwise surface as a
226
+ // deploy failure about a container count with nothing to say about which container is the extra one.
227
+ taskDefinition.node.addValidation({
228
+ validate: () => {
229
+ const containers = taskDefinition.node.children.filter((c) => c instanceof ecs.ContainerDefinition);
230
+ return containers.length > fargate_1.FARGATE_MAX_CONTAINERS
231
+ ? [
232
+ `Odigos: task definition ${taskDefinition.node.id} would have ${containers.length} ` +
233
+ `containers, over the AWS maximum of ${fargate_1.FARGATE_MAX_CONTAINERS}. One of them is the ` +
234
+ 'odigos-agent staging container this instrumentation adds.',
235
+ ]
236
+ : [];
237
+ },
238
+ });
239
+ const state = { sidecar, agentDirs };
240
+ this.taskDefinitions.set(key, state);
241
+ return state;
242
+ }
243
+ /**
244
+ * `OTEL_SERVICE_NAME` for a target, and the one value a caller cannot be allowed to leave to a default.
245
+ *
246
+ * The connector compares it against the workload's name in Odigos, which is the ECS SERVICE name, so
247
+ * guessing — the task definition family, the container name, the construct id — would produce a stack
248
+ * that deploys cleanly and then reports as drifted on a component nothing in the stack makes visible.
249
+ *
250
+ * Read from the L1, not from `service.serviceName`: the L2 property is a token that resolves to a `Ref`
251
+ * to the service even when the stack set the name explicitly, and a `Ref` here is worse than useless —
252
+ * the task definition would reference the service that references it, which CloudFormation rejects as a
253
+ * dependency cycle at deploy time.
254
+ */
255
+ resolveServiceName(target) {
256
+ if (target.serviceName) {
257
+ return target.serviceName;
258
+ }
259
+ if (!target.service) {
260
+ throw new Error(`Odigos: instrumenting container "${target.container.containerName}" needs a service name. ` +
261
+ 'OTEL_SERVICE_NAME must equal the workload\'s name in Odigos, which for a Fargate workload is ' +
262
+ 'the ECS SERVICE name — not the task definition family. Pass `service` to read it off the ' +
263
+ 'service, or `serviceName` when the service lives outside this stack.');
264
+ }
265
+ const cfn = target.service.node.defaultChild;
266
+ const resolved = cfn === undefined ? undefined : aws_cdk_lib_1.Stack.of(target.service).resolve(cfn.serviceName);
267
+ if (typeof resolved === 'string' && resolved !== '' && !aws_cdk_lib_1.Token.isUnresolved(resolved)) {
268
+ return resolved;
269
+ }
270
+ throw new Error(`Odigos: the service for container "${target.container.containerName}" has no explicit physical ` +
271
+ 'name, so CloudFormation generates one — and a generated name is a `Ref` to the service, which ' +
272
+ 'cannot go into the task definition that service runs (CloudFormation rejects the cycle). Set ' +
273
+ '`serviceName` on the ECS service, or pass `serviceName` here to state the name Odigos knows ' +
274
+ 'the workload by.');
275
+ }
276
+ /**
277
+ * Checks the task definition can carry the staged-agent method at all, and warns about the things that
278
+ * are legal but almost certainly a mistake.
279
+ */
280
+ checkTaskDefinition(taskDefinition, container) {
281
+ if (!taskDefinition.isFargateCompatible) {
282
+ // Not fatal — the mechanism is a volume and a copier, which work on the EC2 launch type too. But
283
+ // the connector discovers and judges `aws.fargate-task` workloads, so an EC2-only task definition
284
+ // is instrumented here and invisible there.
285
+ aws_cdk_lib_1.Annotations.of(container).addWarningV2('@odigos/aws-cdk:notFargateCompatible', `Odigos: task definition ${taskDefinition.node.id} is not Fargate-compatible. The staging ` +
286
+ 'container and shared volume will still work on the EC2 launch type, but Odigos discovers ' +
287
+ 'these as `aws.fargate-task` workloads and will not report on an EC2-only task.');
288
+ }
289
+ const cfn = taskDefinition.node.defaultChild;
290
+ const platform = cfn?.runtimePlatform;
291
+ const osFamily = platform?.operatingSystemFamily;
292
+ if (typeof osFamily === 'string' && !aws_cdk_lib_1.Token.isUnresolved(osFamily) && !osFamily.startsWith('LINUX')) {
293
+ throw new Error(`Odigos: task definition ${taskDefinition.node.id} declares operatingSystemFamily ` +
294
+ `"${osFamily}". The Odigos Fargate agents bundle is Linux-only and glibc-based, so a Windows ` +
295
+ 'task definition cannot be instrumented at all.');
296
+ }
297
+ }
298
+ /**
299
+ * The environment applied to one instrumented container.
300
+ *
301
+ * Mirrors `instrumentContainer` in the connector, including the ORDER of decisions: the agent's own
302
+ * activation variables first, then identity, then export, then the marker. Every variable here has a
303
+ * counterpart in the connector's `containerDiff`, which is what a customer's conformance report is
304
+ * built from — so one that is absent, or spelled differently, is reported as a named broken component
305
+ * rather than passing quietly.
306
+ */
307
+ environmentFor(target, recipe, serviceName) {
308
+ const { destination, debug } = this.options;
309
+ const container = target.container;
310
+ const env = {};
311
+ for (const [k, v] of Object.entries(recipe.staticEnv)) {
312
+ // These are set outright, not merged — PHP_INI_SCAN_DIR and RUBYOPT are compared exactly, so there
313
+ // is no room to fold a container's own value in. Silently discarding one is the failure worth
314
+ // naming: RUBYOPT commonly carries flags an application needs to boot.
315
+ const existing = containerEnvValue(container, k);
316
+ if (existing !== undefined && existing !== v) {
317
+ aws_cdk_lib_1.Annotations.of(container).addWarningV2('@odigos/aws-cdk:staticEnvOverwritten', `Odigos: container "${container.containerName}" already sets ${k}="${existing}", which the ` +
318
+ `${recipe.language} agent's activation replaces with "${v}". Odigos compares this variable ` +
319
+ 'exactly, so it cannot merge the two — fold what your application needs into the value ' +
320
+ 'Odigos sets, or leave this container uninstrumented.');
321
+ }
322
+ env[k] = v;
323
+ }
324
+ for (const append of recipe.appendEnv) {
325
+ // Rebuilt from the container's ORIGINAL value so ours is joined rather than assigned over it — and
326
+ // so that a re-synth never accumulates our fragment twice. The separator comes from the pattern,
327
+ // not from an assumption: a space for the *_OPTIONS variables, a colon for PYTHONPATH.
328
+ const existing = target.existingLoaderValue ?? containerEnvValue(container, append.name) ?? '';
329
+ env[append.name] = (0, fargate_recipes_1.evaluateAppendPattern)(append.pattern, existing);
330
+ }
331
+ env[ENV_SERVICE_NAME] = serviceName;
332
+ env[ENV_RESOURCE_ATTRIBUTES] = (0, fargate_recipes_1.fargateResourceAttributes)(aws_cdk_lib_1.Stack.of(container).region);
333
+ const exportTarget = (0, fargate_recipes_1.exportTargetFor)(recipe, destination);
334
+ env[ENV_OTLP_ENDPOINT] = exportTarget.endpoint;
335
+ env[ENV_OTLP_PROTOCOL] = exportTarget.protocol;
336
+ const mismatch = (0, fargate_recipes_1.portProtocolMismatch)(exportTarget.endpoint, exportTarget.protocol);
337
+ if (mismatch) {
338
+ aws_cdk_lib_1.Annotations.of(container).addWarningV2('@odigos/aws-cdk:portProtocolMismatch', `Odigos: ${mismatch}`);
339
+ }
340
+ // All three are written explicitly, unlike Lambda, where an enabled signal's variable is left unset
341
+ // because `otlp` is already the SDK default. The connector's Fargate check compares all three by
342
+ // value, so an omitted one reads as drift on the export component.
343
+ const enabled = (0, collector_config_1.resolvedSignals)(destination);
344
+ if (!enabled.traces && !enabled.metrics && !enabled.logs) {
345
+ throw new Error('Odigos destination accepts no telemetry signals, so the agent would be loaded and produce ' +
346
+ 'nothing. Note that metrics and logs are OFF by default — with `traces: false` the destination ' +
347
+ 'has nothing left unless you also pass `metrics: true` or `logs: true`.');
348
+ }
349
+ env[ENV_TRACES_EXPORTER] = enabled.traces ? EXPORTER_OTLP : collector_config_1.EXPORTER_NONE;
350
+ env[ENV_METRICS_EXPORTER] = enabled.metrics ? EXPORTER_OTLP : collector_config_1.EXPORTER_NONE;
351
+ env[ENV_LOGS_EXPORTER] = enabled.logs ? EXPORTER_OTLP : collector_config_1.EXPORTER_NONE;
352
+ const headers = renderOtlpHeaders(destination.headers);
353
+ if (headers) {
354
+ env[ENV_OTLP_HEADERS] = headers;
355
+ }
356
+ if (debug) {
357
+ env[ENV_OTEL_LOG_LEVEL] = 'debug';
358
+ }
359
+ env[ENV_IAC_MARKER] = JSON.stringify({
360
+ v: MARKER_VERSION,
361
+ source: 'cdk',
362
+ version: layers_1.ODIGOS_VERSION || 'unreleased',
363
+ lang: (0, fargate_recipes_1.languageKeyOf)(target.language),
364
+ });
365
+ return env;
366
+ }
367
+ }
368
+ exports.OdigosFargateInstrumentation = OdigosFargateInstrumentation;
369
+ _a = JSII_RTTI_SYMBOL_1;
370
+ OdigosFargateInstrumentation[_a] = { fqn: "@odigos/aws-cdk.OdigosFargateInstrumentation", version: "0.0.14" };
371
+ /**
372
+ * The value the container was created with for an environment variable, or undefined.
373
+ *
374
+ * `ContainerDefinition` keeps its environment private and offers `addEnvironment` but no reader, so this
375
+ * reaches for the field. That is a contained hack with a specific alternative: without it, appending to a
376
+ * loader variable would mean ASSIGNING over it, and a container whose `NODE_OPTIONS` carries a flag its
377
+ * application needs to boot would stop booting the moment it was instrumented. `existingLoaderValue` on
378
+ * the target is the documented escape hatch if this ever stops working; a shape that is not a plain object
379
+ * degrades to "nothing there", which is the same answer as an uninstrumented container.
380
+ */
381
+ function containerEnvValue(container, name) {
382
+ const env = container.environment;
383
+ if (!env || typeof env !== 'object') {
384
+ return undefined;
385
+ }
386
+ const value = env[name];
387
+ return typeof value === 'string' ? value : undefined;
388
+ }
389
+ /**
390
+ * Renders `OTEL_EXPORTER_OTLP_HEADERS` — a comma-separated `key=value` list, keys sorted so the rendered
391
+ * value is byte-stable across synths and an unchanged destination never looks like a change.
392
+ */
393
+ function renderOtlpHeaders(headers) {
394
+ if (!headers) {
395
+ return '';
396
+ }
397
+ const keys = Object.keys(headers).sort();
398
+ return keys.map((k) => `${k}=${headers[k]}`).join(',');
399
+ }
400
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFyZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9mYXJnYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkNBQThEO0FBQzlELDJDQUEyQztBQUMzQywyQ0FBdUM7QUFDdkMseURBQW9FO0FBQ3BFLGlEQU02QjtBQUM3QiwrQ0FBb0Q7QUFDcEQsdURBUzJCO0FBRzNCLGtFQUFrRTtBQUNsRSxNQUFNLGdCQUFnQixHQUFHLG1CQUFtQixDQUFDO0FBQzdDLHNGQUFzRjtBQUN0RixNQUFNLHVCQUF1QixHQUFHLDBCQUEwQixDQUFDO0FBQzNELHdHQUF3RztBQUN4RyxNQUFNLGlCQUFpQixHQUFHLDZCQUE2QixDQUFDO0FBQ3hELHNFQUFzRTtBQUN0RSxNQUFNLGlCQUFpQixHQUFHLDZCQUE2QixDQUFDO0FBQ3hELHFFQUFxRTtBQUNyRSxNQUFNLGdCQUFnQixHQUFHLDRCQUE0QixDQUFDO0FBQ3RELDhEQUE4RDtBQUM5RCxNQUFNLGtCQUFrQixHQUFHLGdCQUFnQixDQUFDO0FBQzVDLDhDQUE4QztBQUM5QyxNQUFNLG1CQUFtQixHQUFHLHNCQUFzQixDQUFDO0FBQ25ELE1BQU0sb0JBQW9CLEdBQUcsdUJBQXVCLENBQUM7QUFDckQsTUFBTSxpQkFBaUIsR0FBRyxvQkFBb0IsQ0FBQztBQUMvQyxxREFBcUQ7QUFDckQsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDO0FBRTdCOzs7R0FHRztBQUNILE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQztBQUV6Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQztBQUVwQyxnRkFBZ0Y7QUFDaEYsTUFBTSxvQkFBb0IsR0FBRyxhQUFhLENBQUM7QUFFM0M7Ozs7R0FJRztBQUNILE1BQU0sc0JBQXNCLEdBQUcsRUFBRSxDQUFDO0FBOEhsQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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QUMsRUFBRSxjQUFjO1lBQ2pCLE1BQU0sRUFBRSxLQUFLO1lBQ2IsT0FBTyxFQUFFLHVCQUFjLElBQUksWUFBWTtZQUN2QyxJQUFJLEVBQUUsSUFBQSwrQkFBYSxFQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7U0FDckMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDOztBQXpTSCxvRUEwU0M7OztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILFNBQVMsaUJBQWlCLENBQUMsU0FBa0MsRUFBRSxJQUFZO0lBQ3pFLE1BQU0sR0FBRyxHQUFJLFNBQW9FLENBQUMsV0FBVyxDQUFDO0lBQzlGLElBQUksQ0FBQyxHQUFHLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDcEMsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUNELE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4QixPQUFPLE9BQU8sS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDdkQsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsaUJBQWlCLENBQUMsT0FBbUM7SUFDNUQsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2IsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBQ0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN6QyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbm5vdGF0aW9ucywgTGF6eSwgU3RhY2ssIFRva2VuIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgZWNzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBFWFBPUlRFUl9OT05FLCByZXNvbHZlZFNpZ25hbHMgfSBmcm9tICcuL2NvbGxlY3Rvci1jb25maWcnO1xuaW1wb3J0IHtcbiAgRkFSR0FURV9BR0VOVFNfRElSLFxuICBGQVJHQVRFX0FHRU5UU19JTUFHRSxcbiAgRkFSR0FURV9NQVhfQ09OVEFJTkVSUyxcbiAgRkFSR0FURV9TSURFQ0FSX0NPTlRBSU5FUl9OQU1FLFxuICBGQVJHQVRFX1ZPTFVNRV9OQU1FLFxufSBmcm9tICcuL2dlbmVyYXRlZC9mYXJnYXRlJztcbmltcG9ydCB7IE9ESUdPU19WRVJTSU9OIH0gZnJvbSAnLi9nZW5lcmF0ZWQvbGF5ZXJzJztcbmltcG9ydCB7XG4gIEZhcmdhdGVSZWNpcGUsXG4gIGV2YWx1YXRlQXBwZW5kUGF0dGVybixcbiAgZXhwb3J0VGFyZ2V0Rm9yLFxuICBmYXJnYXRlUmVzb3VyY2VBdHRyaWJ1dGVzLFxuICBsYW5ndWFnZUtleU9mLFxuICBwb3J0UHJvdG9jb2xNaXNtYXRjaCxcbiAgcmVjaXBlRm9yLFxuICBzaWRlY2FyQ29tbWFuZCxcbn0gZnJvbSAnLi9mYXJnYXRlLXJlY2lwZXMnO1xuaW1wb3J0IHsgT2RpZ29zRGVzdGluYXRpb24sIE9kaWdvc0ZhcmdhdGVMYW5ndWFnZSB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKiogU2VydmljZSBuYW1lIHJlcG9ydGVkIG9uIGV2ZXJ5IHNwYW4sIG1ldHJpYyBhbmQgbG9nIHJlY29yZC4gKi9cbmNvbnN0IEVOVl9TRVJWSUNFX05BTUUgPSAnT1RFTF9TRVJWSUNFX05BTUUnO1xuLyoqIFJlc291cmNlIGF0dHJpYnV0ZXMgYWRkZWQgdG8gZXZlcnkgcmVjb3JkOiBjbG91ZCBwcm92aWRlciwgcGxhdGZvcm0gYW5kIHJlZ2lvbi4gKi9cbmNvbnN0IEVOVl9SRVNPVVJDRV9BVFRSSUJVVEVTID0gJ09URUxfUkVTT1VSQ0VfQVRUUklCVVRFUyc7XG4vKiogV2hlcmUgdGhlIGFnZW50IGV4cG9ydHMgT1RMUC4gT24gRmFyZ2F0ZSB0aGlzIGlzIHRoZSByZWFsIGRlc3RpbmF0aW9uLCBub3QgYSBsb2NhbGhvc3QgY29sbGVjdG9yLiAqL1xuY29uc3QgRU5WX09UTFBfRU5EUE9JTlQgPSAnT1RFTF9FWFBPUlRFUl9PVExQX0VORFBPSU5UJztcbi8qKiBUaGUgdHJhbnNwb3J0IGZvciB0aGUgZW5kcG9pbnQgYWJvdmUuIFRoZSB0d28gYXJlIG9uZSBkZWNpc2lvbi4gKi9cbmNvbnN0IEVOVl9PVExQX1BST1RPQ09MID0gJ09URUxfRVhQT1JURVJfT1RMUF9QUk9UT0NPTCc7XG4vKiogUGVyLXJlcXVlc3QgaGVhZGVycywgaW4gcHJhY3RpY2UgdGhlIGRlc3RpbmF0aW9uJ3MgY3JlZGVudGlhbC4gKi9cbmNvbnN0IEVOVl9PVExQX0hFQURFUlMgPSAnT1RFTF9FWFBPUlRFUl9PVExQX0hFQURFUlMnO1xuLyoqIFJhaXNlcyBhZ2VudCB2ZXJib3NpdHkgaW50byB0aGUgY29udGFpbmVyJ3MgbG9nIHN0cmVhbS4gKi9cbmNvbnN0IEVOVl9PVEVMX0xPR19MRVZFTCA9ICdPVEVMX0xPR19MRVZFTCc7XG4vKiogVGhlIHRocmVlIHBlci1zaWduYWwgZXhwb3J0ZXIgc3dpdGNoZXMuICovXG5jb25zdCBFTlZfVFJBQ0VTX0VYUE9SVEVSID0gJ09URUxfVFJBQ0VTX0VYUE9SVEVSJztcbmNvbnN0IEVOVl9NRVRSSUNTX0VYUE9SVEVSID0gJ09URUxfTUVUUklDU19FWFBPUlRFUic7XG5jb25zdCBFTlZfTE9HU19FWFBPUlRFUiA9ICdPVEVMX0xPR1NfRVhQT1JURVInO1xuLyoqIFZhbHVlIGEgc3VwcG9ydGVkIHNpZ25hbCdzIGV4cG9ydGVyIGlzIHNldCB0by4gKi9cbmNvbnN0IEVYUE9SVEVSX09UTFAgPSAnb3RscCc7XG5cbi8qKlxuICogU2NoZW1hIHZlcnNpb24gb2YgdGhlIG1hcmtlciBwYXlsb2FkLiBNdXN0IG1hdGNoIGBhcGkuSWFDTWFya2VyVmVyc2lvbmAgaW4gdGhlIGNvbm5lY3RvciDigJQgaXQgaXMgd2hhdFxuICogdGVsbHMgdGhlIGNvbm5lY3RvciBob3cgdG8gcmVhZCB0aGUgcmVzdCBvZiB0aGUgb2JqZWN0LCBzbyBhIGJ1bXBlZCB2ZXJzaW9uIHRoZXJlIGlzIGEgY2hhbmdlIGhlcmUuXG4gKi9cbmNvbnN0IE1BUktFUl9WRVJTSU9OID0gMTtcblxuLyoqXG4gKiBgT0RJR09TX0lBQ2Ag4oCUIHRoZSBtYXJrZXIgcmVjb3JkaW5nIHRoYXQgdGhpcyBjb250YWluZXIgd2FzIGluc3RydW1lbnRlZCBieSBPZGlnb3MgSWFDIHRvb2xpbmcsIGJ5XG4gKiB3aGljaCBwYWNrYWdlIHZlcnNpb24sIGFuZCBmb3Igd2hpY2ggbGFuZ3VhZ2UuXG4gKlxuICogSXQgaXMgUEVSIENPTlRBSU5FUiwgYW5kIGl0IGlzIHRoZSBvbmx5IHRoaW5nIHRoYXQgbWFrZXMgT2RpZ29zIHJlcG9ydCBhIGNvbnRhaW5lciBhcyBpbnN0cnVtZW50ZWRcbiAqIHJhdGhlciB0aGFuIFwiYXdhaXRpbmcgeW91ciBkZXBsb3ltZW50XCIg4oCUIGhvd2V2ZXIgY29tcGxldGVseSB0aGUgcmVzdCBvZiB0aGUgd2lyaW5nIGlzIGFwcGxpZWQuIEEgdGFza1xuICogZGVmaW5pdGlvbiBob2xkaW5nIHR3byBhcHBsaWNhdGlvbnMgbmVlZHMgaXQgb24gYm90aC5cbiAqXG4gKiBUaGUgYGxhbmdgIGZpZWxkIGlzIHRoZSBsb2FkLWJlYXJpbmcgb25lIGhlcmUgKHdoZXJlIExhbWJkYSdzIGlzIGBsYXllcmApLiBUaGUgY29ubmVjdG9yJ3MgY29uZm9ybWFuY2VcbiAqIGNoZWNrIHJlY29uc3RydWN0cyB0aGUgY29udGFpbmVyJ3MgZXhwZWN0ZWQgYWN0aXZhdGlvbiBlbnZpcm9ubWVudCBmcm9tIHRoZSByZWNvcmRlZCBsYW5ndWFnZSwgc28gaXQgaXNcbiAqIHdoYXQgbWFrZXMgXCJpcyB0aGlzIGNvbnRhaW5lciBjb3JyZWN0bHkgaW5zdHJ1bWVudGVkXCIgYW5zd2VyYWJsZSBhdCBhbGwg4oCUIGFuZCBpdCBpcyBjcm9zcy1jaGVja2VkXG4gKiBhZ2FpbnN0IHRoZSBsYW5ndWFnZSB0aGUgY29ubmVjdG9yIHJlc29sdmVzIGluZGVwZW5kZW50bHksIHdoaWNoIGlzIGhvdyBhbiBpbWFnZSBzd2FwcGVkIHVuZGVybmVhdGggdGhlXG4gKiBpbnN0cnVtZW50YXRpb24gaXMgY2F1Z2h0LlxuICpcbiAqIEl0IGlzIE5PVCBgT0RJR09TX01BTkFHRURgLCBhbmQgdGhpcyBjb25zdHJ1Y3QgbmV2ZXIgd3JpdGVzIHRoYXQgb25lLiBUaGF0IGlzIHRoZSBjb25uZWN0b3IncyBvd25cbiAqIHJlY29yZCBvZiBhIG11dGF0aW9uIElUIHBlcmZvcm1lZCwgd2hvc2UgcGF5bG9hZCBpcyB0aGUgc25hcHNob3QgaXQgcmVzdG9yZXMgZnJvbSBvbiByb2xsYmFjay4gQSBDREtcbiAqIHN0YWNrIGhhcyBubyBzdWNoIHNuYXBzaG90IHRvIG9mZmVyLCBiZWNhdXNlIG5vdGhpbmcgd2FzIG11dGF0ZWQg4oCUIHRoZSBjb250YWluZXIgZGVmaW5pdGlvbiBiZWxvdyBJU1xuICogdGhlIGNvbnRhaW5lcidzIGRlZmluaXRpb24uIFdyaXRpbmcgaXQgYnkgaGFuZCB3b3VsZCBjbGFpbSBhIHJvbGxiYWNrIG5vYm9keSByZWNvcmRlZCwgYW5kIHRoZVxuICogY29ubmVjdG9yIHdvdWxkIHRoZW4ganVkZ2UgdGhlIGNvbnRhaW5lciBhZ2FpbnN0IHZhbHVlcyB0aGF0IGRvIG5vdCBleGlzdC5cbiAqL1xuY29uc3QgRU5WX0lBQ19NQVJLRVIgPSAnT0RJR09TX0lBQyc7XG5cbi8qKiBDb25zdHJ1Y3QgaWQgb2YgdGhlIHN0YWdpbmcgY29udGFpbmVyIGluc2lkZSB0aGUgdGFzayBkZWZpbml0aW9uJ3Mgc2NvcGUuICovXG5jb25zdCBTSURFQ0FSX0NPTlNUUlVDVF9JRCA9ICdPZGlnb3NBZ2VudCc7XG5cbi8qKlxuICogTWVtb3J5IHJlc2VydmF0aW9uIGZvciB0aGUgc3RhZ2luZyBjb250YWluZXIgb24gYW4gRUMyLW9ubHkgdGFzayBkZWZpbml0aW9uLCB3aGVyZSBFQ1MgcmVxdWlyZXMgZXZlcnlcbiAqIGNvbnRhaW5lciB0byBkZWNsYXJlIGl0cyBvd24gaWYgdGhlIHRhc2sgZG9lcyBub3QuIE5ldmVyIHNldCBvbiBhIEZhcmdhdGUgdGFzayBkZWZpbml0aW9uIOKAlCBzZWUgdGhlXG4gKiBjYWxsIHNpdGUuXG4gKi9cbmNvbnN0IFNJREVDQVJfRUMyX01FTU9SWV9NSUIgPSA2NDtcblxuLyoqXG4gKiBPcHRpb25zIHNoYXJlZCBieSBldmVyeSBjb250YWluZXIgdGhpcyBjb25zdHJ1Y3QgaW5zdHJ1bWVudHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT2RpZ29zRmFyZ2F0ZUluc3RydW1lbnRhdGlvbk9wdGlvbnMge1xuICAvKipcbiAgICogV2hlcmUgdGhlIGluc3RydW1lbnRlZCBjb250YWluZXJzIGV4cG9ydCB0ZWxlbWV0cnkgdG8uXG4gICAqXG4gICAqIFVubGlrZSBMYW1iZGEsIEJPVEggdHJhbnNwb3J0cyBtYXkgYmUgc2V0IGFuZCBvZnRlbiBzaG91bGQgYmU6IGEgRmFyZ2F0ZSB0YXNrIGhhcyBubyBjb2xsZWN0b3Igb2YgaXRzXG4gICAqIG93biwgc28gZWFjaCBsYW5ndWFnZSdzIGFnZW50IGV4cG9ydHMgdG8gdGhpcyBkZXN0aW5hdGlvbiBpdHNlbGYgYW5kIHRha2VzIHRoZSB0cmFuc3BvcnQgaXQgcHJlZmVycy5cbiAgICogcGhwIGFuZCBydWJ5IGNhbiBvbmx5IHNwZWFrIE9UTFAvSFRUUCBhdCBhbGwuXG4gICAqL1xuICByZWFkb25seSBkZXN0aW5hdGlvbjogT2RpZ29zRGVzdGluYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBhZ2VudHMgYnVuZGxlIHRoZSBzdGFnaW5nIGNvbnRhaW5lciBjb3BpZXMgdGhlIGxhbmd1YWdlIGFnZW50cyBvdXQgb2YuXG4gICAqXG4gICAqIERlZmF1bHRzIHRvIHRoZSBtdWx0aS1hcmNoIGltYWdlIHRoaXMgcGFja2FnZSdzIHJlbGVhc2UgcHVibGlzaGVkLCBhdCB0aGF0IHJlbGVhc2UncyBpbW11dGFibGUgdGFnLlxuICAgKiBPdmVycmlkZSBpdCB0byBtaXJyb3IgdGhlIGltYWdlIGludG8gYSByZWdpc3RyeSB5b3VyIHRhc2tzIGNhbiByZWFjaCDigJQgdGhlIGltYWdlIGlzIHB1bGxlZCBieSBZT1VSXG4gICAqIHRhc2sncyBleGVjdXRpb24gcm9sZSBhdCBldmVyeSB0YXNrIHN0YXJ0LCBzbyBhIHRhc2sgaW4gYSBwcml2YXRlIHN1Ym5ldCB3aXRoIG5vIE5BVCBhbmQgbm9cbiAgICogaW50ZXJmYWNlIGVuZHBvaW50IGNhbm5vdCBwdWxsIHRoZSBkZWZhdWx0LlxuICAgKlxuICAgKiBBIG1pcnJvciBtdXN0IGJlIHRoZSBzYW1lIGJ1bmRsZTogdGhlIGFjdGl2YXRpb24gZW52aXJvbm1lbnQgc2V0IGJlbG93IG5hbWVzIGV4YWN0IHBhdGhzIGluc2lkZSBpdC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgcmVsZWFzZWQgYHJlZ2lzdHJ5Lm9kaWdvcy5pby9vZGlnb3MtZmFyZ2F0ZS1hZ2VudHNgIGltYWdlIGZvciB0aGlzIHBhY2thZ2UgdmVyc2lvblxuICAgKi9cbiAgcmVhZG9ubHkgYWdlbnRzSW1hZ2U/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJhaXNlIGFnZW50IHZlcmJvc2l0eSAoYE9URUxfTE9HX0xFVkVMPWRlYnVnYCkgb24gZXZlcnkgaW5zdHJ1bWVudGVkIGNvbnRhaW5lci5cbiAgICpcbiAgICogVXNlZnVsIHdoaWxlIHdpcmluZyB1cCBhIGRlc3RpbmF0aW9uLCBleHBlbnNpdmUgdG8gbGVhdmUgb24g4oCUIGFuZCBpdCBpcyBjb21wYXJlZDogdGhlIGNvbm5lY3RvclxuICAgKiBleHBlY3RzIHRoZSB2YXJpYWJsZSBBQlNFTlQgdW5sZXNzIGRlYnVnIHRlbGVtZXRyeSBpcyBlbmFibGVkIGZvciB0aGUgY29ubmVjdG9yIHRvbywgc28gbGVhdmluZyB0aGlzXG4gICAqIG9uIGNhbiBpdHNlbGYgYmUgcmVwb3J0ZWQgYXMgZHJpZnQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkZWJ1Zz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogT25lIGNvbnRhaW5lciB0byBpbnN0cnVtZW50LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9kaWdvc0ZhcmdhdGVUYXJnZXQge1xuICAvKipcbiAgICogVGhlIGFwcGxpY2F0aW9uIGNvbnRhaW5lci4gSXRzIHRhc2sgZGVmaW5pdGlvbiBpcyB0YWtlbiBmcm9tIGl0LCBzbyB0aGUgc3RhZ2luZyBjb250YWluZXIsIHRoZSBzaGFyZWRcbiAgICogdm9sdW1lIGFuZCB0aGUgc3RhcnR1cCBkZXBlbmRlbmN5IGFyZSBhZGRlZCB0byB0aGUgcmlnaHQgb25lIGF1dG9tYXRpY2FsbHkuXG4gICAqL1xuICByZWFkb25seSBjb250YWluZXI6IGVjcy5Db250YWluZXJEZWZpbml0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgbGFuZ3VhZ2Ugd2hvc2UgYWdlbnQgdG8gc3RhZ2UgYW5kIGFjdGl2YXRlLlxuICAgKlxuICAgKiBTdGF0ZWQgcmF0aGVyIHRoYW4gZGV0ZWN0ZWQg4oCUIGEgY29udGFpbmVyIGRlY2xhcmVzIGFuIGltYWdlLCBub3QgYSBydW50aW1lLCBhbmQgcmVzb2x2aW5nIGEgbGFuZ3VhZ2VcbiAgICogZnJvbSBhbiBpbWFnZSBtZWFucyBwdWxsaW5nIGl0LlxuICAgKi9cbiAgcmVhZG9ubHkgbGFuZ3VhZ2U6IE9kaWdvc0ZhcmdhdGVMYW5ndWFnZTtcblxuICAvKipcbiAgICogYE9URUxfU0VSVklDRV9OQU1FYCBmb3IgdGhpcyBjb250YWluZXIuXG4gICAqXG4gICAqIFRISVMgTVVTVCBNQVRDSCBUSEUgV09SS0xPQUQnUyBOQU1FIElOIE9ESUdPUywgd2hpY2ggZm9yIGEgRmFyZ2F0ZSB3b3JrbG9hZCBpcyB0aGUgRUNTIFNFUlZJQ0UgbmFtZSDigJRcbiAgICogbm90IHRoZSB0YXNrIGRlZmluaXRpb24gZmFtaWx5IGFuZCBub3QgdGhlIGNvbnRhaW5lciBuYW1lLiBBIGRpZmZlcmVudCB2YWx1ZSBpcyByZXBvcnRlZCBhc1xuICAgKiBpbnN0cnVtZW50YXRpb24gZHJpZnQgcmF0aGVyIHRoYW4gdHJlYXRlZCBhcyBhIG5hbWluZyBwcmVmZXJlbmNlLlxuICAgKlxuICAgKiBQYXNzIGBzZXJ2aWNlYCBpbnN0ZWFkIHRvIHJlYWQgaXQgb2ZmIHRoZSBzZXJ2aWNlLCBvciBzZXQgdGhpcyB3aGVuIHRoZSBzZXJ2aWNlIGlzIGRlZmluZWQgZWxzZXdoZXJlXG4gICAqIChhIGRpZmZlcmVudCBzdGFjaywgVGVycmFmb3JtLCB0aGUgY29uc29sZSkuIE9uZSBvZiB0aGUgdHdvIGlzIHJlcXVpcmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRha2VuIGZyb20gYHNlcnZpY2VgXG4gICAqL1xuICByZWFkb25seSBzZXJ2aWNlTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEVDUyBzZXJ2aWNlIHRoYXQgcnVucyB0aGlzIHRhc2sgZGVmaW5pdGlvbiwgdXNlZCBvbmx5IHRvIHJlYWQgaXRzIG5hbWUuXG4gICAqXG4gICAqIEl0cyBwaHlzaWNhbCBuYW1lIGhhcyB0byBiZSBvbmUgeW91ciBzdGFjayBTRVQsIG5vdCBvbmUgQ2xvdWRGb3JtYXRpb24gZ2VuZXJhdGVzOiBhIGdlbmVyYXRlZCBuYW1lIGlzXG4gICAqIGEgYFJlZmAgdG8gdGhlIHNlcnZpY2UsIGFuZCBhIHNlcnZpY2UncyBvd24gdGFzayBkZWZpbml0aW9uIHJlZmVyZW5jaW5nIGl0IGlzIGEgZGVwZW5kZW5jeSBjeWNsZVxuICAgKiBDbG91ZEZvcm1hdGlvbiByZWplY3RzIGF0IGRlcGxveSB0aW1lLiBBIGdlbmVyYXRlZCBuYW1lIHRocm93cyBhdCBzeW50aCBwb2ludGluZyBhdCBgc2VydmljZU5hbWVgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGBzZXJ2aWNlTmFtZWAgbXVzdCBiZSBnaXZlbiBpbnN0ZWFkXG4gICAqL1xuICByZWFkb25seSBzZXJ2aWNlPzogZWNzLkJhc2VTZXJ2aWNlO1xuXG4gIC8qKlxuICAgKiBUaGUgYXBwbGljYXRpb24ncyBydW50aW1lIHZlcnNpb24gYXMgYG1ham9yLm1pbm9yYCDigJQgZm9yIGV4YW1wbGUgYFwiOC4zXCJgLlxuICAgKlxuICAgKiBSZXF1aXJlZCBmb3IgcGhwIGFuZCBydWJ5LCB3aG9zZSBhZ2VudHMgYXJlIGxhaWQgZG93biBwZXIgcnVudGltZSB2ZXJzaW9uIGluIHRoZSBidW5kbGUsIGFuZCB0aGVcbiAgICogdmVyc2lvbiBzZWxlY3RzIHRoZSBwYXRoIHRoZWlyIGFjdGl2YXRpb24gdmFyaWFibGVzIHBvaW50IGF0LiBJZ25vcmVkIGJ5IGV2ZXJ5IG90aGVyIGxhbmd1YWdlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmU7IHJlcXVpcmVkIGZvciBwaHAgYW5kIHJ1YnlcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnRpbWVWZXJzaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgdmFsdWUgdGhpcyBjb250YWluZXIgYWxyZWFkeSBuZWVkcyBpbiBpdHMgbG9hZGVyIHZhcmlhYmxlIChgSkFWQV9UT09MX09QVElPTlNgLCBgTk9ERV9PUFRJT05TYCBvclxuICAgKiBgUFlUSE9OUEFUSGApLCB3aGljaCB0aGUgT2RpZ29zIGZyYWdtZW50IGlzIGpvaW5lZCB0byByYXRoZXIgdGhhbiByZXBsYWNpbmcuXG4gICAqXG4gICAqIE9ubHkgbmVlZGVkIGFzIGFuIE9WRVJSSURFLiBUaGUgY29uc3RydWN0IHJlYWRzIHRoZSB2YWx1ZSB0aGUgY29udGFpbmVyIHdhcyBjcmVhdGVkIHdpdGggYW5kIGFwcGVuZHNcbiAgICogdG8gaXQsIHNvIGEgY29udGFpbmVyIHRoYXQgc2V0cyBpdHMgb3duIGBKQVZBX1RPT0xfT1BUSU9OU2AgaW4gYGFkZENvbnRhaW5lcmAga2VlcHMgaXQuIFBhc3MgdGhpcyB3aGVuXG4gICAqIHRoZSB2YWx1ZSBpcyBub3QgdmlzaWJsZSBhdCBzeW50aCDigJQgc2V0IGJ5IGFuIGBlbnZpcm9ubWVudEZpbGVzYCBlbnRyeSwgaW5qZWN0ZWQgYnkgdGhlIGltYWdlJ3Mgb3duXG4gICAqIGBFTlZgLCBvciBzdXBwbGllZCB0aHJvdWdoIGBzZWNyZXRzYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSByZWFkIGZyb20gdGhlIGNvbnRhaW5lcidzIG93biBlbnZpcm9ubWVudFxuICAgKi9cbiAgcmVhZG9ubHkgZXhpc3RpbmdMb2FkZXJWYWx1ZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wcyBmb3Ige0BsaW5rIE9kaWdvc0ZhcmdhdGVJbnN0cnVtZW50YXRpb259LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9kaWdvc0ZhcmdhdGVJbnN0cnVtZW50YXRpb25Qcm9wcyBleHRlbmRzIE9kaWdvc0ZhcmdhdGVJbnN0cnVtZW50YXRpb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIENvbnRhaW5lcnMgdG8gaW5zdHJ1bWVudCBvbiBjb25zdHJ1Y3Rpb24uIE1vcmUgY2FuIGJlIGFkZGVkIHdpdGggYGluc3RydW1lbnQoKWAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0cz86IE9kaWdvc0ZhcmdhdGVUYXJnZXRbXTtcbn1cblxuLyoqIFBlci10YXNrLWRlZmluaXRpb24gc3RhdGU6IHRoZSBzdGFnaW5nIGNvbnRhaW5lciwgYW5kIHdoYXQgaXQgaGFzIGJlZW4gYXNrZWQgdG8gc3RhZ2UuICovXG5pbnRlcmZhY2UgVGFza0RlZmluaXRpb25TdGF0ZSB7XG4gIHJlYWRvbmx5IHNpZGVjYXI6IGVjcy5Db250YWluZXJEZWZpbml0aW9uO1xuICByZWFkb25seSBhZ2VudERpcnM6IFNldDxzdHJpbmc+O1xufVxuXG4vKipcbiAqIEluc3RydW1lbnRzIEVDUyBGYXJnYXRlIGNvbnRhaW5lcnMgd2l0aCB0aGUgT2RpZ29zIE9wZW5UZWxlbWV0cnkgYWdlbnRzLlxuICpcbiAqIGBgYHRzXG4gKiBjb25zdCBvZGlnb3MgPSBuZXcgT2RpZ29zRmFyZ2F0ZUluc3RydW1lbnRhdGlvbih0aGlzLCAnT2RpZ29zJywge1xuICogICBkZXN0aW5hdGlvbjogeyBodHRwRW5kcG9pbnQ6ICdodHRwczovL290bHAuZXhhbXBsZS5jb206NDMxOCcgfSxcbiAqIH0pO1xuICogb2RpZ29zLmluc3RydW1lbnQoe1xuICogICBjb250YWluZXI6IGFwaUNvbnRhaW5lcixcbiAqICAgbGFuZ3VhZ2U6IE9kaWdvc0ZhcmdhdGVMYW5ndWFnZS5KQVZBLFxuICogICBzZXJ2aWNlOiBhcGlTZXJ2aWNlLFxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiAjIyBXaGF0IGl0IGRvZXMgdG8gdGhlIHRhc2sgZGVmaW5pdGlvblxuICpcbiAqIEZvdXIgbW92ZXMsIHdoaWNoIGFyZSBvbmUgbWVjaGFuaXNtIGFuZCBvbmx5IHdvcmsgdG9nZXRoZXIg4oCUIHRoZSBFQ1MgYWRhcHRhdGlvbiBvZiB0aGUgT2Rpa29zXG4gKiBpbml0LWNvbnRhaW5lciBtb3VudCBtZXRob2Q6XG4gKlxuICogIDEuIGEgYmFyZS1uYW1lIHRhc2sgdm9sdW1lIChgb2RpZ29zLWFnZW50YCksIHdoaWNoIG9uIEZhcmdhdGUgaXMgYW4gZXBoZW1lcmFsLXN0b3JhZ2UgYmluZCBtb3VudFxuICogICAgIHNjb3BlZCB0byB0aGUgdGFzaztcbiAqICAyLiBhIE5PTi1FU1NFTlRJQUwgYG9kaWdvcy1hZ2VudGAgY29udGFpbmVyIHRoYXQgY29waWVzIHRoZSBsYW5ndWFnZSBhZ2VudHMgb3V0IG9mIHRoZSBhZ2VudHMgYnVuZGxlXG4gKiAgICAgaW50byB0aGF0IHZvbHVtZSBhbmQgZXhpdHMgMDtcbiAqICAzLiB0aGUgdm9sdW1lIG1vdW50ZWQgcmVhZC1vbmx5IGF0IGAvdmFyL29kaWdvc2AgaW4gZWFjaCBpbnN0cnVtZW50ZWQgY29udGFpbmVyLCB3aGljaCBkZXBlbmRzIG9uIHRoZVxuICogICAgIHN0YWdpbmcgY29udGFpbmVyIHdpdGggY29uZGl0aW9uIGBTVUNDRVNTYCDigJQgb25seSB2YWxpZCBhZ2FpbnN0IGEgbm9uLWVzc2VudGlhbCBjb250YWluZXIsIHdoaWNoIGlzXG4gKiAgICAgd2h5ICgyKSBpcyBub24tZXNzZW50aWFsO1xuICogIDQuIHRoZSBsYW5ndWFnZSdzIGFjdGl2YXRpb24gZW52aXJvbm1lbnQsIHRoZSBPVExQIGV4cG9ydCBlbnZpcm9ubWVudCwgYW5kIHRoZSBgT0RJR09TX0lBQ2AgbWFya2VyIG9uXG4gKiAgICAgZWFjaCBpbnN0cnVtZW50ZWQgY29udGFpbmVyLlxuICpcbiAqIFRoZXJlIGlzIE9ORSBzdGFnaW5nIGNvbnRhaW5lciBwZXIgdGFzayBkZWZpbml0aW9uIGhvd2V2ZXIgbWFueSBsYW5ndWFnZXMgdGhlIHRhc2sgaG9sZHM7IGl0cyBjb21tYW5kXG4gKiBpcyB0aGUgdW5pb24gb2YgZXZlcnkgaW5zdHJ1bWVudGVkIGNvbnRhaW5lcidzIGFnZW50IGRpcmVjdG9yaWVzLCBhbmQgaXQgaXMgYnVpbHQgbGF6aWx5IHNvIGNvbnRhaW5lcnNcbiAqIGluc3RydW1lbnRlZCBsYXRlciBhcmUgaW5jbHVkZWQuXG4gKlxuICogIyMgV2hlcmUgdGhlIHRlbGVtZXRyeSBnb2VzXG4gKlxuICogU3RyYWlnaHQgdG8geW91ciBkZXN0aW5hdGlvbiwgZnJvbSBpbnNpZGUgdGhlIGFwcGxpY2F0aW9uIHByb2Nlc3MuIFRoaXMgaXMgdGhlIHN1YnN0YW50aXZlIGRpZmZlcmVuY2VcbiAqIGZyb20gTGFtYmRhOiB0aGVyZSBpcyBubyBjb2xsZWN0b3IgaW4gdGhlIHRhc2sgdG8gaGFuZCBhIGJhdGNoIHRvLCBzbyBhIHNsb3cgb3IgdW5yZWFjaGFibGUgZGVzdGluYXRpb25cbiAqIGlzIGZlbHQgYnkgdGhlIGFwcGxpY2F0aW9uJ3Mgb3duIGV4cG9ydGVyIHJhdGhlciB0aGFuIGFic29yYmVkIGFmdGVyIGEgcmVzcG9uc2UgaGFzIGJlZW4gcmV0dXJuZWQuXG4gKlxuICogIyMgV2hhdCBpdCBkZWxpYmVyYXRlbHkgZG9lcyBOT1QgZG9cbiAqXG4gKiBUaGVyZSBpcyBubyBhc3BlY3QgdGhhdCBzd2VlcHMgYSBzY29wZSwgYXMgdGhlcmUgaXMgZm9yIExhbWJkYS4gQW4gYXNwZWN0IHRoZXJlIHdvcmtzIGJlY2F1c2UgYVxuICogZnVuY3Rpb24gREVDTEFSRVMgaXRzIHJ1bnRpbWU7IGEgY29udGFpbmVyIGRlY2xhcmVzIGFuIGltYWdlLCBhbmQgYSBsYW5ndWFnZSBndWVzc2VkIGZyb20gYW4gaW1hZ2UgbmFtZVxuICogd291bGQgc2lsZW50bHkgbWlzLWluc3RydW1lbnQgdGhlIG9uZXMgaXQgZ290IHdyb25nIOKAlCBzdGFnaW5nIGEgSmF2YSBhZ2VudCBpbnRvIGEgUHl0aG9uIGNvbnRhaW5lclxuICogbGVhdmVzIGl0IHVuaW5zdHJ1bWVudGVkLCBhbmQgYSBgSkFWQV9UT09MX09QVElPTlNgIG9uIGEgSlZNLWxlc3MgaW1hZ2UgaXMgc2ltcGx5IGlnbm9yZWQsIHNvIG5vdGhpbmdcbiAqIGZhaWxzIGxvdWRseSBlbm91Z2ggdG8gbm90aWNlLlxuICpcbiAqICMjIERvIG5vdCBhbHNvIGluc3RydW1lbnQgdGhlc2Ugc2VydmljZXMgd2l0aCB0aGUgY29ubmVjdG9yXG4gKlxuICogVGhlIGNvbm5lY3RvciBpbnN0cnVtZW50cyBsaXZlIHNlcnZpY2VzIGJ5IHJlZ2lzdGVyaW5nIGEgbmV3IHRhc2stZGVmaW5pdGlvbiByZXZpc2lvbiBhbmQgdXBkYXRpbmcgdGhlXG4gKiBzZXJ2aWNlIHRvIGl0LCByZWNvbmNpbGluZyB0byBpdHMgb3duIGRlc2lyZWQgc3RhdGUgb24gZXZlcnkgcGFzcy4gQSBzZXJ2aWNlIGluc3RydW1lbnRlZCBoZXJlIGFuZCBhbHNvXG4gKiBlbmFibGVkIGFzIGEgY29ubmVjdG9yIHNvdXJjZSBlbmRzIHVwIG93bmVkIGJ5IGJvdGg6IGVhY2ggYGNkayBkZXBsb3lgIHJlYXNzZXJ0cyB0aGUgc3RhY2snc1xuICogZGVmaW5pdGlvbiwgZWFjaCByZWNvbmNpbGUgcmVhc3NlcnRzIHRoZSBjb25uZWN0b3IncywgYW5kIGV2ZXJ5IHJvdW5kIHRyaXAgcmVnaXN0ZXJzIGEgcmV2aXNpb24gYW5kXG4gKiByb2xscyB0aGUgc2VydmljZS4gQ2hvb3NlIG9uZSBwZXIgc2VydmljZS5cbiAqL1xuZXhwb3J0IGNsYXNzIE9kaWdvc0ZhcmdhdGVJbnN0cnVtZW50YXRpb24gZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IE9kaWdvc0ZhcmdhdGVJbnN0cnVtZW50YXRpb25PcHRpb25zO1xuICBwcml2YXRlIHJlYWRvbmx5IGFnZW50c0ltYWdlOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgdGFza0RlZmluaXRpb25zID0gbmV3IE1hcDxzdHJpbmcsIFRhc2tEZWZpbml0aW9uU3RhdGU+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW5zdHJ1bWVudGVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE9kaWdvc0ZhcmdhdGVJbnN0cnVtZW50YXRpb25Qcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gICAgdGhpcy5vcHRpb25zID0gcHJvcHM7XG5cbiAgICBjb25zdCBpbWFnZSA9IHByb3BzLmFnZW50c0ltYWdlID8/IEZBUkdBVEVfQUdFTlRTX0lNQUdFO1xuICAgIGlmICghaW1hZ2UpIHtcbiAgICAgIC8vIEVtcHR5IG9ubHkgaW4gYSBjaGVja291dCBidWlsdCBiZWZvcmUgdGhlIGZpcnN0IHJlbGVhc2UuIEZhaWxpbmcgaGVyZSBpcyB0aGUgcG9pbnQ6IHRoZVxuICAgICAgLy8gYWx0ZXJuYXRpdmUgaXMgYSB0YXNrIGRlZmluaXRpb24gd2hvc2Ugc3RhZ2luZyBjb250YWluZXIgbmFtZXMgYSB0YWcgdGhhdCBkb2VzIG5vdCBleGlzdCwgd2hpY2hcbiAgICAgIC8vIHN1cmZhY2VzIGFzIGEgdGFzayB0aGF0IHdpbGwgbm90IHN0YXJ0LCBhdCBkZXBsb3kgdGltZSwgaW4gYSBwbGFjZSB0aGF0IHNheXMgbm90aGluZyBhYm91dCB3aHkuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdPZGlnb3M6IHRoaXMgYnVpbGQgb2YgQG9kaWdvcy9hd3MtY2RrIGhhcyBubyBGYXJnYXRlIGFnZW50cyBpbWFnZSBiYWtlZCBpbiDigJQgaXQgd2FzIGJ1aWx0ICcgK1xuICAgICAgICAgICdiZWZvcmUgdGhlIGZpcnN0IHJlbGVhc2UuIFVzZSBhIHJlbGVhc2VkIHZlcnNpb24gb2YgdGhlIHBhY2thZ2UsIG9yIHBhc3MgYGFnZW50c0ltYWdlYCAnICtcbiAgICAgICAgICAnZXhwbGljaXRseS4nLFxuICAgICAgKTtcbiAgICB9XG4gICAgdGhpcy5hZ2VudHNJbWFnZSA9IGltYWdlO1xuXG4gICAgZm9yIChjb25zdCB0YXJnZXQgb2YgcHJvcHMudGFyZ2V0cyA/PyBbXSkge1xuICAgICAgdGhpcy5pbnN0cnVtZW50KHRhcmdldCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluc3RydW1lbnRzIG9uZSBjb250YWluZXIuIElkZW1wb3RlbnQg4oCUIGluc3RydW1lbnRpbmcgdGhlIHNhbWUgY29udGFpbmVyIHR3aWNlIGlzIGEgbm8tb3AgcmF0aGVyIHRoYW5cbiAgICogYSBkb3VibGVkIGxvYWRlciB2YWx1ZS5cbiAgICovXG4gIHB1YmxpYyBpbnN0cnVtZW50KHRhcmdldDogT2RpZ29zRmFyZ2F0ZVRhcmdldCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRhcmdldC5jb250YWluZXI7XG4gICAgY29uc3Qga2V5ID0gY29udGFpbmVyLm5vZGUucGF0aDtcbiAgICBpZiAodGhpcy5pbnN0cnVtZW50ZWQuaGFzKGtleSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0YXNrRGVmaW5pdGlvbiA9IGNvbnRhaW5lci50YXNrRGVmaW5pdGlvbjtcbiAgICBjb25zdCByZWNpcGUgPSByZWNpcGVGb3IodGFyZ2V0Lmxhbmd1YWdlLCB0YXJnZXQucnVudGltZVZlcnNpb24pO1xuICAgIGNvbnN0IHNlcnZpY2VOYW1lID0gdGhpcy5yZXNvbHZlU2VydmljZU5hbWUodGFyZ2V0KTtcblxuICAgIHRoaXMuY2hlY2tUYXNrRGVmaW5pdGlvbih0YXNrRGVmaW5pdGlvbiwgY29udGFpbmVyKTtcbiAgICB0aGlzLmluc3RydW1lbnRlZC5hZGQoa2V5KTtcblxuICAgIGNvbnN0IHN0YXRlID0gdGhpcy50YXNrRGVmaW5pdGlvblN0YXRlKHRhc2tEZWZpbml0aW9uKTtcbiAgICBmb3IgKGNvbnN0IGRpciBvZiByZWNpcGUuYWdlbnREaXJzKSB7XG4gICAgICBzdGF0ZS5hZ2VudERpcnMuYWRkKGRpcik7XG4gICAgfVxuXG4gICAgLy8gUmVhZC1vbmx5OiB0aGUgYWdlbnRzIGFyZSBvbmx5IHJlYWQgaGVyZSwgYW5kIHRoZSBzdGFnaW5nIGNvbnRhaW5lciBvd25zIHRoZSB3cml0ZXMuXG4gICAgY29udGFpbmVyLmFkZE1vdW50UG9pbnRzKHtcbiAgICAgIHNvdXJjZVZvbHVtZTogRkFSR0FURV9WT0xVTUVfTkFNRSxcbiAgICAgIGNvbnRhaW5lclBhdGg6IEZBUkdBVEVfQUdFTlRTX0RJUixcbiAgICAgIHJlYWRPbmx5OiB0cnVlLFxuICAgIH0pO1xuICAgIC8vIFNVQ0NFU1MsIG5vdCBTVEFSVDogdGhlIGFnZW50IGZpbGVzIGhhdmUgdG8gYmUgb24gZGlzayBiZWZvcmUgdGhlIGFwcGxpY2F0aW9uIHByb2Nlc3MgYmVnaW5zLCBhbmRcbiAgICAvLyB0aGUgc3RhZ2luZyBjb250YWluZXIgZXhpdHMgYXMgc29vbiBhcyB0aGV5IGFyZS5cbiAgICBjb250YWluZXIuYWRkQ29udGFpbmVyRGVwZW5kZW5jaWVzKHtcbiAgICAgIGNvbnRhaW5lcjogc3RhdGUuc2lkZWNhcixcbiAgICAgIGNvbmRpdGlvbjogZWNzLkNvbnRhaW5lckRlcGVuZGVuY3lDb25kaXRpb24uU1VDQ0VTUyxcbiAgICB9KTtcblxuICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyh0aGlzLmVudmlyb25tZW50Rm9yKHRhcmdldCwgcmVjaXBlLCBzZXJ2aWNlTmFtZSkpKSB7XG4gICAgICBjb250YWluZXIuYWRkRW52aXJvbm1lbnQobmFtZSwgdmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBJbnN0cnVtZW50cyBldmVyeSB0YXJnZXQgaW4gdGhlIGxpc3QuICovXG4gIHB1YmxpYyBpbnN0cnVtZW50QWxsKHRhcmdldHM6IE9kaWdvc0ZhcmdhdGVUYXJnZXRbXSk6IHZvaWQge1xuICAgIGZvciAoY29uc3QgdGFyZ2V0IG9mIHRhcmdldHMpIHtcbiAgICAgIHRoaXMuaW5zdHJ1bWVudCh0YXJnZXQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgdGFzayBkZWZpbml0aW9uJ3Mgc3RhZ2luZyBjb250YWluZXIgYW5kIHZvbHVtZSwgY3JlYXRlZCBvbmNlIGFuZCBzaGFyZWQgYnkgZXZlcnkgY29udGFpbmVyIGluIGl0LlxuICAgKlxuICAgKiBUaGUgY29tbWFuZCBpcyBhIGxhenkgbGlzdCByYXRoZXIgdGhhbiBhIGxpdGVyYWwgYmVjYXVzZSB0aGUgdW5pb24gaXQgcmVuZGVycyBpcyBub3Qga25vd24gdW50aWxcbiAgICogc3ludGhlc2lzOiBhIHRhc2sgZGVmaW5pdGlvbiBob2xkaW5nIGEgSmF2YSBhbmQgYSBQeXRob24gYXBwbGljYXRpb24gaXMgaW5zdHJ1bWVudGVkIGJ5IHR3b1xuICAgKiBgaW5zdHJ1bWVudCgpYCBjYWxscywgYW5kIHRoZSBzaW5nbGUgc3RhZ2luZyBjb250YWluZXIgaGFzIHRvIHN0YWdlIGJvdGguIFRoZSBjb25uZWN0b3IgY29tcGFyZXMgdGhpc1xuICAgKiBjb21tYW5kIGFnYWluc3QgZXhhY3RseSB0aGF0IHVuaW9uLCBzbyBhIHN0YWxlIG9uZSBpcyByZXBvcnRlZCBhcyBkcmlmdCBvbiB0aGUgd2hvbGUgdGFzayBkZWZpbml0aW9uXG4gICAqIGFuZCBsZWF2ZXMgb25lIG9mIHRoZSBjb250YWluZXJzIHdpdGggbm8gYWdlbnQgb24gZGlzay5cbiAgICovXG4gIHByaXZhdGUgdGFza0RlZmluaXRpb25TdGF0ZSh0YXNrRGVmaW5pdGlvbjogZWNzLlRhc2tEZWZpbml0aW9uKTogVGFza0RlZmluaXRpb25TdGF0ZSB7XG4gICAgY29uc3Qga2V5ID0gdGFza0RlZmluaXRpb24ubm9kZS5wYXRoO1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy50YXNrRGVmaW5pdGlvbnMuZ2V0KGtleSk7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gZXhpc3Rpbmc7XG4gICAgfVxuXG4gICAgLy8gQSBiYXJlLW5hbWUgdm9sdW1lIOKAlCBubyBob3N0LCBkb2NrZXIgb3IgRUZTIGNvbmZpZ3VyYXRpb24g4oCUIGlzIGEgRmFyZ2F0ZSBlcGhlbWVyYWwtc3RvcmFnZSBiaW5kXG4gICAgLy8gbW91bnQgc2NvcGVkIHRvIHRoZSB0YXNrLCB3aGljaCBpcyBleGFjdGx5IHRoZSBzaGFyZWQgc3RhZ2luZyBhcmVhIG5lZWRlZCBhbmQgdGhlIG9ubHkga2luZCBGYXJnYXRlXG4gICAgLy8gb2ZmZXJzICh0aGVyZSBpcyBubyB0bXBmcykuXG4gICAgdGFza0RlZmluaXRpb24uYWRkVm9sdW1lKHsgbmFtZTogRkFSR0FURV9WT0xVTUVfTkFNRSB9KTtcblxuICAgIGNvbnN0IGFnZW50RGlycyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IHNpZGVjYXIgPSB0YXNrRGVmaW5pdGlvbi5hZGRDb250YWluZXIoU0lERUNBUl9DT05TVFJVQ1RfSUQsIHtcbiAgICAgIGNvbnRhaW5lck5hbWU6IEZBUkdBVEVfU0lERUNBUl9DT05UQUlORVJfTkFNRSxcbiAgICAgIGltYWdlOiBlY3MuQ29udGFpbmVySW1hZ2UuZnJvbVJlZ2lzdHJ5KHRoaXMuYWdlbnRzSW1hZ2UpLFxuICAgICAgLy8gTm9uLWVzc2VudGlhbCBpcyBub3QgYSBwcmVmZXJlbmNlOiBpdCBpcyB3aGF0IG1ha2VzIHRoZSBTVUNDRVNTIGRlcGVuZGVuY3kgYWJvdmUgbGVnYWwsIGFuZCBpdCBpc1xuICAgICAgLy8gd2hhdCBzdG9wcyBhIGNvcGllciB0aGF0IGhhcyBmaW5pc2hlZCBpdHMgam9iIGZyb20gZmFpbGluZyB0aGUgd2hvbGUgdGFzayBieSBleGl0aW5nLlxuICAgICAgZXNzZW50aWFsOiBmYWxzZSxcbiAgICAgIGNvbW1hbmQ6IExhenkubGlzdCh7IHByb2R1Y2U6ICgpID0+IHNpZGVjYXJDb21tYW5kKFsuLi5hZ2VudERpcnNdKSB9KSxcbiAgICAgIC8vIEZhcmdhdGUgYWxsb2NhdGVzIG1lbW9yeSBhdCB0aGUgdGFzayBsZXZlbCwgc28gdGhlIHN0YWdpbmcgY29udGFpbmVyIGRlY2xhcmVzIG5vbmUgdGhlcmUg4oCUIHdoaWNoXG4gICAgICAvLyBrZWVwcyB0aGUgcmVuZGVyZWQgY29udGFpbmVyIGJ5dGUtaWRlbnRpY2FsIHRvIHdoYXQgdGhlIGNvbm5lY3RvciB3cml0ZXMuIEFuIEVDMi1vbmx5IHRhc2tcbiAgICAgIC8vIGRlZmluaXRpb24gd2l0aG91dCB0YXNrLWxldmVsIG1lbW9yeSByZXF1aXJlcyBldmVyeSBjb250YWluZXIgdG8gZGVjbGFyZSBpdHMgb3duLCBzbyBvbmUgaXMgc2V0XG4gICAgICAvLyBmb3IgdGhhdCBjYXNlIGFsb25lLiBBIHNvZnQgcmVzZXJ2YXRpb24sIGFuZCBnZW5lcm91czogdGhlIGNvbnRhaW5lciBpcyBidXN5Ym94IHJ1bm5pbmcgYGNwYC5cbiAgICAgIG1lbW9yeVJlc2VydmF0aW9uTWlCOiB0YXNrRGVmaW5pdGlvbi5pc0ZhcmdhdGVDb21wYXRpYmxlID8gdW5kZWZpbmVkIDogU0lERUNBUl9FQzJfTUVNT1JZX01JQixcbiAgICB9KTtcbiAgICAvLyBXcml0YWJsZSBoZXJlIOKAlCB0aGlzIGlzIHRoZSBjb250YWluZXIgdGhhdCBwdXRzIHRoZSBmaWxlcyB0aGVyZS4gYHJlYWRPbmx5YCBpcyByZXF1aXJlZCBieSBDREsnc1xuICAgIC8vIE1vdW50UG9pbnQgc3RydWN0IHdoZXJlIHRoZSBjb25uZWN0b3Igc2ltcGx5IG9taXRzIGl0OyBmYWxzZSBpcyB3aGF0IGFuIG9taXR0ZWQgdmFsdWUgbWVhbnMsIGFuZCB0aGVcbiAgICAvLyBjb25uZWN0b3IncyB0YXNrLWxldmVsIGNoZWNrIGNvbXBhcmVzIHRoZSBzdGFnaW5nIGNvbnRhaW5lcidzIGltYWdlLCBlc3NlbnRpYWxpdHkgYW5kIGNvbW1hbmQsIG5vdFxuICAgIC8vIGl0cyBtb3VudHMsIHNvIHNwZWxsaW5nIG91dCB0aGUgZGVmYXVsdCBpcyBub3QgZHJpZnQuXG4gICAgc2lkZWNhci5hZGRNb3VudFBvaW50cyh7XG4gICAgICBzb3VyY2VWb2x1bWU6IEZBUkdBVEVfVk9MVU1FX05BTUUsXG4gICAgICBjb250YWluZXJQYXRoOiBGQVJHQVRFX0FHRU5UU19ESVIsXG4gICAgICByZWFkT25seTogZmFsc2UsXG4gICAgfSk7XG5cbiAgICAvLyBSZWdpc3RlcmVkIGhlcmUsIHdpdGggdGhlIHN0YWdpbmcgY29udGFpbmVyLCBzbyBpdCBpcyBhZGRlZCBvbmNlIHBlciB0YXNrIGRlZmluaXRpb24gaG93ZXZlciBtYW55XG4gICAgLy8gY29udGFpbmVycyBhcmUgaW5zdHJ1bWVudGVkIGluIGl0IOKAlCBhbmQgY291bnRlZCBhdCBzeW50aCwgc28gY29udGFpbmVycyBhZGRlZCBhZnRlciB0aGlzIGNhbGwgYXJlXG4gICAgLy8gaW5jbHVkZWQuIEFXUyByZWplY3RzIGEgUmVnaXN0ZXJUYXNrRGVmaW5pdGlvbiBvdmVyIHRoZSBsaW1pdCwgd2hpY2ggd291bGQgb3RoZXJ3aXNlIHN1cmZhY2UgYXMgYVxuICAgIC8vIGRlcGxveSBmYWlsdXJlIGFib3V0IGEgY29udGFpbmVyIGNvdW50IHdpdGggbm90aGluZyB0byBzYXkgYWJvdXQgd2hpY2ggY29udGFpbmVyIGlzIHRoZSBleHRyYSBvbmUuXG4gICAgdGFza0RlZmluaXRpb24ubm9kZS5hZGRWYWxpZGF0aW9uKHtcbiAgICAgIHZhbGlkYXRlOiAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lcnMgPSB0YXNrRGVmaW5pdGlvbi5ub2RlLmNoaWxkcmVuLmZpbHRlcigoYykgPT4gYyBpbnN0YW5jZW9mIGVjcy5Db250YWluZXJEZWZpbml0aW9uKTtcbiAgICAgICAgcmV0dXJuIGNvbnRhaW5lcnMubGVuZ3RoID4gRkFSR0FURV9NQVhfQ09OVEFJTkVSU1xuICAgICAgICAgID8gW1xuICAgICAgICAgICAgYE9kaWdvczogdGFzayBkZWZpbml0aW9uICR7dGFza0RlZmluaXRpb24ubm9kZS5pZH0gd291bGQgaGF2ZSAke2NvbnRhaW5lcnMubGVuZ3RofSBgICtcbiAgICAgICAgICAgICAgICBgY29udGFpbmVycywgb3ZlciB0aGUgQVdTIG1heGltdW0gb2YgJHtGQVJHQVRFX01BWF9DT05UQUlORVJTfS4gT25lIG9mIHRoZW0gaXMgdGhlIGAgK1xuICAgICAgICAgICAgICAgICdvZGlnb3MtYWdlbnQgc3RhZ2luZyBjb250YWluZXIgdGhpcyBpbnN0cnVtZW50YXRpb24gYWRkcy4nLFxuICAgICAgICAgIF1cbiAgICAgICAgICA6IFtdO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHN0YXRlOiBUYXNrRGVmaW5pdGlvblN0YXRlID0geyBzaWRlY2FyLCBhZ2VudERpcnMgfTtcbiAgICB0aGlzLnRhc2tEZWZpbml0aW9ucy5zZXQoa2V5LCBzdGF0ZSk7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIGBPVEVMX1NFUlZJQ0VfTkFNRWAgZm9yIGEgdGFyZ2V0LCBhbmQgdGhlIG9uZSB2YWx1ZSBhIGNhbGxlciBjYW5ub3QgYmUgYWxsb3dlZCB0byBsZWF2ZSB0byBhIGRlZmF1bHQuXG4gICAqXG4gICAqIFRoZSBjb25uZWN0b3IgY29tcGFyZXMgaXQgYWdhaW5zdCB0aGUgd29ya2xvYWQncyBuYW1lIGluIE9kaWdvcywgd2hpY2ggaXMgdGhlIEVDUyBTRVJWSUNFIG5hbWUsIHNvXG4gICAqIGd1ZXNzaW5nIOKAlCB0aGUgdGFzayBkZWZpbml0aW9uIGZhbWlseSwgdGhlIGNvbnRhaW5lciBuYW1lLCB0aGUgY29uc3RydWN0IGlkIOKAlCB3b3VsZCBwcm9kdWNlIGEgc3RhY2tcbiAgICogdGhhdCBkZXBsb3lzIGNsZWFubHkgYW5kIHRoZW4gcmVwb3J0cyBhcyBkcmlmdGVkIG9uIGEgY29tcG9uZW50IG5vdGhpbmcgaW4gdGhlIHN0YWNrIG1ha2VzIHZpc2libGUuXG4gICAqXG4gICAqIFJlYWQgZnJvbSB0aGUgTDEsIG5vdCBmcm9tIGBzZXJ2aWNlLnNlcnZpY2VOYW1lYDogdGhlIEwyIHByb3BlcnR5IGlzIGEgdG9rZW4gdGhhdCByZXNvbHZlcyB0byBhIGBSZWZgXG4gICAqIHRvIHRoZSBzZXJ2aWNlIGV2ZW4gd2hlbiB0aGUgc3RhY2sgc2V0IHRoZSBuYW1lIGV4cGxpY2l0bHksIGFuZCBhIGBSZWZgIGhlcmUgaXMgd29yc2UgdGhhbiB1c2VsZXNzIOKAlFxuICAgKiB0aGUgdGFzayBkZWZpbml0aW9uIHdvdWxkIHJlZmVyZW5jZSB0aGUgc2VydmljZSB0aGF0IHJlZmVyZW5jZXMgaXQsIHdoaWNoIENsb3VkRm9ybWF0aW9uIHJlamVjdHMgYXMgYVxuICAgKiBkZXBlbmRlbmN5IGN5Y2xlIGF0IGRlcGxveSB0aW1lLlxuICAgKi9cbiAgcHJpdmF0ZSByZXNvbHZlU2VydmljZU5hbWUodGFyZ2V0OiBPZGlnb3NGYXJnYXRlVGFyZ2V0KTogc3RyaW5nIHtcbiAgICBpZiAodGFyZ2V0LnNlcnZpY2VOYW1lKSB7XG4gICAgICByZXR1cm4gdGFyZ2V0LnNlcnZpY2VOYW1lO1xuICAgIH1cbiAgICBpZiAoIXRhcmdldC5zZXJ2aWNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBPZGlnb3M6IGluc3RydW1lbnRpbmcgY29udGFpbmVyIFwiJHt0YXJnZXQuY29udGFpbmVyLmNvbnRhaW5lck5hbWV9XCIgbmVlZHMgYSBzZXJ2aWNlIG5hbWUuIGAgK1xuICAgICAgICAgICdPVEVMX1NFUlZJQ0VfTkFNRSBtdXN0IGVxdWFsIHRoZSB3b3JrbG9hZFxcJ3MgbmFtZSBpbiBPZGlnb3MsIHdoaWNoIGZvciBhIEZhcmdhdGUgd29ya2xvYWQgaXMgJyArXG4gICAgICAgICAgJ3RoZSBFQ1MgU0VSVklDRSBuYW1lIOKAlCBub3QgdGhlIHRhc2sgZGVmaW5pdGlvbiBmYW1pbHkuIFBhc3MgYHNlcnZpY2VgIHRvIHJlYWQgaXQgb2ZmIHRoZSAnICtcbiAgICAgICAgICAnc2VydmljZSwgb3IgYHNlcnZpY2VOYW1lYCB3aGVuIHRoZSBzZXJ2aWNlIGxpdmVzIG91dHNpZGUgdGhpcyBzdGFjay4nLFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgY2ZuID0gdGFyZ2V0LnNlcnZpY2Uubm9kZS5kZWZhdWx0Q2hpbGQgYXMgZWNzLkNmblNlcnZpY2UgfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgcmVzb2x2ZWQgPSBjZm4gPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IFN0YWNrLm9mKHRhcmdldC5zZXJ2aWNlKS5yZXNvbHZlKGNmbi5zZXJ2aWNlTmFtZSk7XG4gICAgaWYgKHR5cGVvZiByZXNvbHZlZCA9PT0gJ3N0cmluZycgJiYgcmVzb2x2ZWQgIT09ICcnICYmICFUb2tlbi5pc1VucmVzb2x2ZWQocmVzb2x2ZWQpKSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZWQ7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBPZGlnb3M6IHRoZSBzZXJ2aWNlIGZvciBjb250YWluZXIgXCIke3RhcmdldC5jb250YWluZXIuY29udGFpbmVyTmFtZX1cIiBoYXMgbm8gZXhwbGljaXQgcGh5c2ljYWwgYCArXG4gICAgICAgICduYW1lLCBzbyBDbG91ZEZvcm1hdGlvbiBnZW5lcmF0ZXMgb25lIOKAlCBhbmQgYSBnZW5lcmF0ZWQgbmFtZSBpcyBhIGBSZWZgIHRvIHRoZSBzZXJ2aWNlLCB3aGljaCAnICtcbiAgICAgICAgJ2Nhbm5vdCBnbyBpbnRvIHRoZSB0YXNrIGRlZmluaXRpb24gdGhhdCBzZXJ2aWNlIHJ1bnMgKENsb3VkRm9ybWF0aW9uIHJlamVjdHMgdGhlIGN5Y2xlKS4gU2V0ICcgK1xuICAgICAgICAnYHNlcnZpY2VOYW1lYCBvbiB0aGUgRUNTIHNlcnZpY2UsIG9yIHBhc3MgYHNlcnZpY2VOYW1lYCBoZXJlIHRvIHN0YXRlIHRoZSBuYW1lIE9kaWdvcyBrbm93cyAnICtcbiAgICAgICAgJ3RoZSB3b3JrbG9hZCBieS4nLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHRoZSB0YXNrIGRlZmluaXRpb24gY2FuIGNhcnJ5IHRoZSBzdGFnZWQtYWdlbnQgbWV0aG9kIGF0IGFsbCwgYW5kIHdhcm5zIGFib3V0IHRoZSB0aGluZ3MgdGhhdFxuICAgKiBhcmUgbGVnYWwgYnV0IGFsbW9zdCBjZXJ0YWlubHkgYSBtaXN0YWtlLlxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja1Rhc2tEZWZpbml0aW9uKHRhc2tEZWZpbml0aW9uOiBlY3MuVGFza0RlZmluaXRpb24sIGNvbnRhaW5lcjogZWNzLkNvbnRhaW5lckRlZmluaXRpb24pOiB2b2lkIHtcbiAgICBpZiAoIXRhc2tEZWZpbml0aW9uLmlzRmFyZ2F0ZUNvbXBhdGlibGUpIHtcbiAgICAgIC8vIE5vdCBmYXRhbCDigJQgdGhlIG1lY2hhbmlzbSBpcyBhIHZvbHVtZSBhbmQgYSBjb3BpZXIsIHdoaWNoIHdvcmsgb24gdGhlIEVDMiBsYXVuY2ggdHlwZSB0b28uIEJ1dFxuICAgICAgLy8gdGhlIGNvbm5lY3RvciBkaXNjb3ZlcnMgYW5kIGp1ZGdlcyBgYXdzLmZhcmdhdGUtdGFza2Agd29ya2xvYWRzLCBzbyBhbiBFQzItb25seSB0YXNrIGRlZmluaXRpb25cbiAgICAgIC8vIGlzIGluc3RydW1lbnRlZCBoZXJlIGFuZCBpbnZpc2libGUgdGhlcmUuXG4gICAgICBBbm5vdGF0aW9ucy5vZihjb250YWluZXIpLmFkZFdhcm5pbmdWMihcbiAgICAgICAgJ0BvZGlnb3MvYXdzLWNkazpub3RGYXJnYXRlQ29tcGF0aWJsZScsXG4gICAgICAgIGBPZGlnb3M6IHRhc2sgZGVmaW5pdGlvbiAke3Rhc2tEZWZpbml0aW9uLm5vZGUuaWR9IGlzIG5vdCBGYXJnYXRlLWNvbXBhdGlibGUuIFRoZSBzdGFnaW5nIGAgK1xuICAgICAgICAgICdjb250YWluZXIgYW5kIHNoYXJlZCB2b2x1bWUgd2lsbCBzdGlsbCB3b3JrIG9uIHRoZSBFQzIgbGF1bmNoIHR5cGUsIGJ1dCBPZGlnb3MgZGlzY292ZXJzICcgK1xuICAgICAgICAgICd0aGVzZSBhcyBgYXdzLmZhcmdhdGUtdGFza2Agd29ya2xvYWRzIGFuZCB3aWxsIG5vdCByZXBvcnQgb24gYW4gRUMyLW9ubHkgdGFzay4nLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBjZm4gPSB0YXNrRGVmaW5pdGlvbi5ub2RlLmRlZmF1bHRDaGlsZCBhcyBlY3MuQ2ZuVGFza0RlZmluaXRpb24gfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgcGxhdGZvcm0gPSBjZm4/LnJ1bnRpbWVQbGF0Zm9ybSBhcyBlY3MuQ2ZuVGFza0RlZmluaXRpb24uUnVudGltZVBsYXRmb3JtUHJvcGVydHkgfCB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb3NGYW1pbHkgPSBwbGF0Zm9ybT8ub3BlcmF0aW5nU3lzdGVtRmFtaWx5O1xuICAgIGlmICh0eXBlb2Ygb3NGYW1pbHkgPT09ICdzdHJpbmcnICYmICFUb2tlbi5pc1VucmVzb2x2ZWQob3NGYW1pbHkpICYmICFvc0ZhbWlseS5zdGFydHNXaXRoKCdMSU5VWCcpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBPZGlnb3M6IHRhc2sgZGVmaW5pdGlvbiAke3Rhc2tEZWZpbml0aW9uLm5vZGUuaWR9IGRlY2xhcmVzIG9wZXJhdGluZ1N5c3RlbUZhbWlseSBgICtcbiAgICAgICAgICBgXCIke29zRmFtaWx5fVwiLiBUaGUgT2RpZ29zIEZhcmdhdGUgYWdlbnRzIGJ1bmRsZSBpcyBMaW51eC1vbmx5IGFuZCBnbGliYy1iYXNlZCwgc28gYSBXaW5kb3dzIGAgK1xuICAgICAgICAgICd0YXNrIGRlZmluaXRpb24gY2Fubm90IGJlIGluc3RydW1lbnRlZCBhdCBhbGwuJyxcbiAgICAgICk7XG4gICAgfVxuXG4gIH1cblxuICAvKipcbiAgICogVGhlIGVudmlyb25tZW50IGFwcGxpZWQgdG8gb25lIGluc3RydW1lbnRlZCBjb250YWluZXIuXG4gICAqXG4gICAqIE1pcnJvcnMgYGluc3RydW1lbnRDb250YWluZXJgIGluIHRoZSBjb25uZWN0b3IsIGluY2x1ZGluZyB0aGUgT1JERVIgb2YgZGVjaXNpb25zOiB0aGUgYWdlbnQncyBvd25cbiAgICogYWN0aXZhdGlvbiB2YXJpYWJsZXMgZmlyc3QsIHRoZW4gaWRlbnRpdHksIHRoZW4gZXhwb3J0LCB0aGVuIHRoZSBtYXJrZXIuIEV2ZXJ5IHZhcmlhYmxlIGhlcmUgaGFzIGFcbiAgICogY291bnRlcnBhcnQgaW4gdGhlIGNvbm5lY3RvcidzIGBjb250YWluZXJEaWZmYCwgd2hpY2ggaXMgd2hhdCBhIGN1c3RvbWVyJ3MgY29uZm9ybWFuY2UgcmVwb3J0IGlzXG4gICAqIGJ1aWx0IGZyb20g4oCUIHNvIG9uZSB0aGF0IGlzIGFic2VudCwgb3Igc3BlbGxlZCBkaWZmZXJlbnRseSwgaXMgcmVwb3J0ZWQgYXMgYSBuYW1lZCBicm9rZW4gY29tcG9uZW50XG4gICAqIHJhdGhlciB0aGFuIHBhc3NpbmcgcXVpZXRseS5cbiAgICovXG4gIHByaXZhdGUgZW52aXJvbm1lbnRGb3IoXG4gICAgdGFyZ2V0OiBPZGlnb3NGYXJnYXRlVGFyZ2V0LFxuICAgIHJlY2lwZTogRmFyZ2F0ZVJlY2lwZSxcbiAgICBzZXJ2aWNlTmFtZTogc3RyaW5nLFxuICApOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9IHtcbiAgICBjb25zdCB7IGRlc3RpbmF0aW9uLCBkZWJ1ZyB9ID0gdGhpcy5vcHRpb25zO1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRhcmdldC5jb250YWluZXI7XG4gICAgY29uc3QgZW52OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG5cbiAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyhyZWNpcGUuc3RhdGljRW52KSkge1xuICAgICAgLy8gVGhlc2UgYXJlIHNldCBvdXRyaWdodCwgbm90IG1lcmdlZCDigJQgUEhQX0lOSV9TQ0FOX0RJUiBhbmQgUlVCWU9QVCBhcmUgY29tcGFyZWQgZXhhY3RseSwgc28gdGhlcmVcbiAgICAgIC8vIGlzIG5vIHJvb20gdG8gZm9sZCBhIGNvbnRhaW5lcidzIG93biB2YWx1ZSBpbi4gU2lsZW50bHkgZGlzY2FyZGluZyBvbmUgaXMgdGhlIGZhaWx1cmUgd29ydGhcbiAgICAgIC8vIG5hbWluZzogUlVCWU9QVCBjb21tb25seSBjYXJyaWVzIGZsYWdzIGFuIGFwcGxpY2F0aW9uIG5lZWRzIHRvIGJvb3QuXG4gICAgICBjb25zdCBleGlzdGluZyA9IGNvbnRhaW5lckVudlZhbHVlKGNvbnRhaW5lciwgayk7XG4gICAgICBpZiAoZXhpc3RpbmcgIT09IHVuZGVmaW5lZCAmJiBleGlzdGluZyAhPT0gdikge1xuICAgICAgICBBbm5vdGF0aW9ucy5vZihjb250YWluZXIpLmFkZFdhcm5pbmdWMihcbiAgICAgICAgICAnQG9kaWdvcy9hd3MtY2RrOnN0YXRpY0Vudk92ZXJ3cml0dGVuJyxcbiAgICAgICAgICBgT2RpZ29zOiBjb250YWluZXIgXCIke2NvbnRhaW5lci5jb250YWluZXJOYW1lfVwiIGFscmVhZHkgc2V0cyAke2t9PVwiJHtleGlzdGluZ31cIiwgd2hpY2ggdGhlIGAgK1xuICAgICAgICAgICAgYCR7cmVjaXBlLmxhbmd1YWdlfSBhZ2VudCdzIGFjdGl2YXRpb24gcmVwbGFjZXMgd2l0aCBcIiR7dn1cIi4gT2RpZ29zIGNvbXBhcmVzIHRoaXMgdmFyaWFibGUgYCArXG4gICAgICAgICAgICAnZXhhY3RseSwgc28gaXQgY2Fubm90IG1lcmdlIHRoZSB0d28g4oCUIGZvbGQgd2hhdCB5b3VyIGFwcGxpY2F0aW9uIG5lZWRzIGludG8gdGhlIHZhbHVlICcgK1xuICAgICAgICAgICAgJ09kaWdvcyBzZXRzLCBvciBsZWF2ZSB0aGlzIGNvbnRhaW5lciB1bmluc3RydW1lbnRlZC4nLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgZW52W2tdID0gdjtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGFwcGVuZCBvZiByZWNpcGUuYXBwZW5kRW52KSB7XG4gICAgICAvLyBSZWJ1aWx0IGZyb20gdGhlIGNvbnRhaW5lcidzIE9SSUdJTkFMIHZhbHVlIHNvIG91cnMgaXMgam9pbmVkIHJhdGhlciB0aGFuIGFzc2lnbmVkIG92ZXIgaXQg4oCUIGFuZFxuICAgICAgLy8gc28gdGhhdCBhIHJlLXN5bnRoIG5ldmVyIGFjY3VtdWxhdGVzIG91ciBmcmFnbWVudCB0d2ljZS4gVGhlIHNlcGFyYXRvciBjb21lcyBmcm9tIHRoZSBwYXR0ZXJuLFxuICAgICAgLy8gbm90IGZyb20gYW4gYXNzdW1wdGlvbjogYSBzcGFjZSBmb3IgdGhlICpfT1BUSU9OUyB2YXJpYWJsZXMsIGEgY29sb24gZm9yIFBZVEhPTlBBVEguXG4gICAgICBjb25zdCBleGlzdGluZyA9IHRhcmdldC5leGlzdGluZ0xvYWRlclZhbHVlID8/IGNvbnRhaW5lckVudlZhbHVlKGNvbnRhaW5lciwgYXBwZW5kLm5hbWUpID8/ICcnO1xuICAgICAgZW52W2FwcGVuZC5uYW1lXSA9IGV2YWx1YXRlQXBwZW5kUGF0dGVybihhcHBlbmQucGF0dGVybiwgZXhpc3RpbmcpO1xuICAgIH1cblxuICAgIGVudltFTlZfU0VSVklDRV9OQU1FXSA9IHNlcnZpY2VOYW1lO1xuICAgIGVudltFTlZfUkVTT1VSQ0VfQVRUUklCVVRFU10gPSBmYXJnYXRlUmVzb3VyY2VBdHRyaWJ1dGVzKFN0YWNrLm9mKGNvbnRhaW5lcikucmVnaW9uKTtcblxuICAgIGNvbnN0IGV4cG9ydFRhcmdldCA9IGV4cG9ydFRhcmdldEZvcihyZWNpcGUsIGRlc3RpbmF0aW9uKTtcbiAgICBlbnZbRU5WX09UTFBfRU5EUE9JTlRdID0gZXhwb3J0VGFyZ2V0LmVuZHBvaW50O1xuICAgIGVudltFTlZfT1RMUF9QUk9UT0NPTF0gPSBleHBvcnRUYXJnZXQucHJvdG9jb2w7XG4gICAgY29uc3QgbWlzbWF0Y2ggPSBwb3J0UHJvdG9jb2xNaXNtYXRjaChleHBvcnRUYXJnZXQuZW5kcG9pbnQsIGV4cG9ydFRhcmdldC5wcm90b2NvbCk7XG4gICAgaWYgKG1pc21hdGNoKSB7XG4gICAgICBBbm5vdGF0aW9ucy5vZihjb250YWluZXIpLmFkZFdhcm5pbmdWMignQG9kaWdvcy9hd3MtY2RrOnBvcnRQcm90b2NvbE1pc21hdGNoJywgYE9kaWdvczogJHttaXNtYXRjaH1gKTtcbiAgICB9XG5cbiAgICAvLyBBbGwgdGhyZWUgYXJlIHdyaXR0ZW4gZXhwbGljaXRseSwgdW5saWtlIExhbWJkYSwgd2hlcmUgYW4gZW5hYmxlZCBzaWduYWwncyB2YXJpYWJsZSBpcyBsZWZ0IHVuc2V0XG4gICAgLy8gYmVjYXVzZSBgb3RscGAgaXMgYWxyZWFkeSB0aGUgU0RLIGRlZmF1bHQuIFRoZSBjb25uZWN0b3IncyBGYXJnYXRlIGNoZWNrIGNvbXBhcmVzIGFsbCB0aHJlZSBieVxuICAgIC8vIHZhbHVlLCBzbyBhbiBvbWl0dGVkIG9uZSByZWFkcyBhcyBkcmlmdCBvbiB0aGUgZXhwb3J0IGNvbXBvbmVudC5cbiAgICBjb25zdCBlbmFibGVkID0gcmVzb2x2ZWRTaWduYWxzKGRlc3RpbmF0aW9uKTtcbiAgICBpZiAoIWVuYWJsZWQudHJhY2VzICYmICFlbmFibGVkLm1ldHJpY3MgJiYgIWVuYWJsZWQubG9ncykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnT2RpZ29zIGRlc3RpbmF0aW9uIGFjY2VwdHMgbm8gdGVsZW1ldHJ5IHNpZ25hbHMsIHNvIHRoZSBhZ2VudCB3b3VsZCBiZSBsb2FkZWQgYW5kIHByb2R1Y2UgJyArXG4gICAgICAgICAgJ25vdGhpbmcuIE5vdGUgdGhhdCBtZXRyaWNzIGFuZCBsb2dzIGFyZSBPRkYgYnkgZGVmYXVsdCDigJQgd2l0aCBgdHJhY2VzOiBmYWxzZWAgdGhlIGRlc3RpbmF0aW9uICcgK1xuICAgICAgICAgICdoYXMgbm90aGluZyBsZWZ0IHVubGVzcyB5b3UgYWxzbyBwYXNzIGBtZXRyaWNzOiB0cnVlYCBvciBgbG9nczogdHJ1ZWAuJyxcbiAgICAgICk7XG4gICAgfVxuICAgIGVudltFTlZfVFJBQ0VTX0VYUE9SVEVSXSA9IGVuYWJsZWQudHJhY2VzID8gRVhQT1JURVJfT1RMUCA6IEVYUE9SVEVSX05PTkU7XG4gICAgZW52W0VOVl9NRVRSSUNTX0VYUE9SVEVSXSA9IGVuYWJsZWQubWV0cmljcyA/IEVYUE9SVEVSX09UTFAgOiBFWFBPUlRFUl9OT05FO1xuICAgIGVudltFTlZfTE9HU19FWFBPUlRFUl0gPSBlbmFibGVkLmxvZ3MgPyBFWFBPUlRFUl9PVExQIDogRVhQT1JURVJfTk9ORTtcblxuICAgIGNvbnN0IGhlYWRlcnMgPSByZW5kZXJPdGxwSGVhZGVycyhkZXN0aW5hdGlvbi5oZWFkZXJzKTtcbiAgICBpZiAoaGVhZGVycykge1xuICAgICAgZW52W0VOVl9PVExQX0hFQURFUlNdID0gaGVhZGVycztcbiAgICB9XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIGVudltFTlZfT1RFTF9MT0dfTEVWRUxdID0gJ2RlYnVnJztcbiAgICB9XG5cbiAgICBlbnZbRU5WX0lBQ19NQVJLRVJdID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgdjogTUFSS0VSX1ZFUlNJT04sXG4gICAgICBzb3VyY2U6ICdjZGsnLFxuICAgICAgdmVyc2lvbjogT0RJR09TX1ZFUlNJT04gfHwgJ3VucmVsZWFzZWQnLFxuICAgICAgbGFuZzogbGFuZ3VhZ2VLZXlPZih0YXJnZXQubGFuZ3VhZ2UpLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGVudjtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSB2YWx1ZSB0aGUgY29udGFpbmVyIHdhcyBjcmVhdGVkIHdpdGggZm9yIGFuIGVudmlyb25tZW50IHZhcmlhYmxlLCBvciB1bmRlZmluZWQuXG4gKlxuICogYENvbnRhaW5lckRlZmluaXRpb25gIGtlZXBzIGl0cyBlbnZpcm9ubWVudCBwcml2YXRlIGFuZCBvZmZlcnMgYGFkZEVudmlyb25tZW50YCBidXQgbm8gcmVhZGVyLCBzbyB0aGlzXG4gKiByZWFjaGVzIGZvciB0aGUgZmllbGQuIFRoYXQgaXMgYSBjb250YWluZWQgaGFjayB3aXRoIGEgc3BlY2lmaWMgYWx0ZXJuYXRpdmU6IHdpdGhvdXQgaXQsIGFwcGVuZGluZyB0byBhXG4gKiBsb2FkZXIgdmFyaWFibGUgd291bGQgbWVhbiBBU1NJR05JTkcgb3ZlciBpdCwgYW5kIGEgY29udGFpbmVyIHdob3NlIGBOT0RFX09QVElPTlNgIGNhcnJpZXMgYSBmbGFnIGl0c1xuICogYXBwbGljYXRpb24gbmVlZHMgdG8gYm9vdCB3b3VsZCBzdG9wIGJvb3RpbmcgdGhlIG1vbWVudCBpdCB3YXMgaW5zdHJ1bWVudGVkLiBgZXhpc3RpbmdMb2FkZXJWYWx1ZWAgb25cbiAqIHRoZSB0YXJnZXQgaXMgdGhlIGRvY3VtZW50ZWQgZXNjYXBlIGhhdGNoIGlmIHRoaXMgZXZlciBzdG9wcyB3b3JraW5nOyBhIHNoYXBlIHRoYXQgaXMgbm90IGEgcGxhaW4gb2JqZWN0XG4gKiBkZWdyYWRlcyB0byBcIm5vdGhpbmcgdGhlcmVcIiwgd2hpY2ggaXMgdGhlIHNhbWUgYW5zd2VyIGFzIGFuIHVuaW5zdHJ1bWVudGVkIGNvbnRhaW5lci5cbiAqL1xuZnVuY3Rpb24gY29udGFpbmVyRW52VmFsdWUoY29udGFpbmVyOiBlY3MuQ29udGFpbmVyRGVmaW5pdGlvbiwgbmFtZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZW52ID0gKGNvbnRhaW5lciBhcyB1bmtub3duIGFzIHsgZW52aXJvbm1lbnQ/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9IH0pLmVudmlyb25tZW50O1xuICBpZiAoIWVudiB8fCB0eXBlb2YgZW52ICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3QgdmFsdWUgPSBlbnZbbmFtZV07XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUgOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmVuZGVycyBgT1RFTF9FWFBPUlRFUl9PVExQX0hFQURFUlNgIOKAlCBhIGNvbW1hLXNlcGFyYXRlZCBga2V5PXZhbHVlYCBsaXN0LCBrZXlzIHNvcnRlZCBzbyB0aGUgcmVuZGVyZWRcbiAqIHZhbHVlIGlzIGJ5dGUtc3RhYmxlIGFjcm9zcyBzeW50aHMgYW5kIGFuIHVuY2hhbmdlZCBkZXN0aW5hdGlvbiBuZXZlciBsb29rcyBsaWtlIGEgY2hhbmdlLlxuICovXG5mdW5jdGlvbiByZW5kZXJPdGxwSGVhZGVycyhoZWFkZXJzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSk6IHN0cmluZyB7XG4gIGlmICghaGVhZGVycykge1xuICAgIHJldHVybiAnJztcbiAgfVxuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoaGVhZGVycykuc29ydCgpO1xuICByZXR1cm4ga2V5cy5tYXAoKGspID0+IGAke2t9PSR7aGVhZGVyc1trXX1gKS5qb2luKCcsJyk7XG59XG4iXX0=
@@ -0,0 +1,44 @@
1
+ /**
2
+ * GENERATED FILE — DO NOT EDIT.
3
+ *
4
+ * Produced by cdk/scripts/generate.ts from artifacts.json and manifest/layers.json.
5
+ * Run `npm run generate` (or `npm run build`) to refresh it.
6
+ *
7
+ * Odigos artifact version: v0.0.14
8
+ */
9
+ /**
10
+ * The multi-arch agents bundle the staging container copies from, at the tag this package's release
11
+ * published. Empty before the first release.
12
+ */
13
+ export declare const FARGATE_AGENTS_IMAGE = "registry.odigos.io/odigos-fargate-agents:v0.0.14";
14
+ /** Shared task-volume mount path the language agents are staged into, in every container. */
15
+ export declare const FARGATE_AGENTS_DIR = "/var/odigos";
16
+ /** Where the agents bundle holds the agent files; the staging container copies from here to there. */
17
+ export declare const FARGATE_IMAGE_AGENTS_DIR = "/instrumentations";
18
+ /** Container name of the run-to-completion staging container. Matched exactly by the connector. */
19
+ export declare const FARGATE_SIDECAR_CONTAINER_NAME = "odigos-agent";
20
+ /** Name of the shared task volume the agents are staged into. */
21
+ export declare const FARGATE_VOLUME_NAME = "odigos-agent";
22
+ /** AWS's cap on containers per task definition — the staging container needs one of them. */
23
+ export declare const FARGATE_MAX_CONTAINERS = 10;
24
+ /** Odigos distros module version the recipes below were mirrored from. */
25
+ export declare const FARGATE_DISTROS_VERSION = "v1.33.0-pre4";
26
+ /** An append-style loader variable, carrying the distro's own ReplacePattern. */
27
+ export interface GeneratedAppendEnvVar {
28
+ readonly name: string;
29
+ readonly pattern: string;
30
+ }
31
+ /** How one language's agent is staged and activated. Mirrored from the OSS Odigos community distros. */
32
+ export interface GeneratedFargateRecipe {
33
+ readonly agentDirs: string[];
34
+ readonly staticEnv: {
35
+ [key: string]: string;
36
+ };
37
+ readonly appendEnv: GeneratedAppendEnvVar[];
38
+ readonly otlpProtocol: string;
39
+ readonly protocolFixed: boolean;
40
+ readonly requiresRuntimeVersion: boolean;
41
+ }
42
+ export declare const FARGATE_LANGUAGES: {
43
+ [language: string]: GeneratedFargateRecipe;
44
+ };