cdk8s-plus-36 0.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/.jsii +105714 -0
  2. package/CODE_OF_CONDUCT.md +3 -0
  3. package/CONTRIBUTING.md +185 -0
  4. package/DCO +34 -0
  5. package/LICENSE +202 -0
  6. package/NOTICE +1 -0
  7. package/OWNERS.md +5 -0
  8. package/README.md +21 -34
  9. package/SECURITY.md +5 -0
  10. package/cdk8s.yaml +13 -0
  11. package/docs/java.md +156096 -0
  12. package/docs/plus/config-map.md +98 -0
  13. package/docs/plus/container.md +133 -0
  14. package/docs/plus/cronjob.md +67 -0
  15. package/docs/plus/deployment.md +232 -0
  16. package/docs/plus/horizontal-pod-autoscaler.md +226 -0
  17. package/docs/plus/ingress.md +68 -0
  18. package/docs/plus/job.md +48 -0
  19. package/docs/plus/namespace.md +58 -0
  20. package/docs/plus/network-policy.md +341 -0
  21. package/docs/plus/pod.md +455 -0
  22. package/docs/plus/pv.md +82 -0
  23. package/docs/plus/pvc.md +77 -0
  24. package/docs/plus/rbac.md +104 -0
  25. package/docs/plus/secret.md +32 -0
  26. package/docs/plus/service-account.md +35 -0
  27. package/docs/plus/service.md +41 -0
  28. package/docs/plus/volume.md +84 -0
  29. package/docs/python.md +167536 -0
  30. package/docs/typescript.md +145485 -0
  31. package/git-hooks/README.md +9 -0
  32. package/git-hooks/prepare-commit-msg +18 -0
  33. package/git-hooks/setup.sh +10 -0
  34. package/lib/_action.d.ts +26 -0
  35. package/lib/_action.js +72 -0
  36. package/lib/api-resource.d.ts +298 -0
  37. package/lib/api-resource.js +438 -0
  38. package/lib/base.d.ts +79 -0
  39. package/lib/base.js +124 -0
  40. package/lib/config-map.d.ts +126 -0
  41. package/lib/config-map.js +199 -0
  42. package/lib/container.d.ts +1057 -0
  43. package/lib/container.js +944 -0
  44. package/lib/cron-job.d.ts +138 -0
  45. package/lib/cron-job.js +170 -0
  46. package/lib/daemon-set.d.ts +45 -0
  47. package/lib/daemon-set.js +91 -0
  48. package/lib/deployment.d.ts +235 -0
  49. package/lib/deployment.js +274 -0
  50. package/lib/handler.d.ts +62 -0
  51. package/lib/handler.js +88 -0
  52. package/lib/horizontal-pod-autoscaler.d.ts +500 -0
  53. package/lib/horizontal-pod-autoscaler.js +629 -0
  54. package/lib/imports/k8s.d.ts +27283 -0
  55. package/lib/imports/k8s.js +20112 -0
  56. package/lib/index.d.ts +26 -0
  57. package/lib/index.js +66 -0
  58. package/lib/ingress.d.ts +230 -0
  59. package/lib/ingress.js +282 -0
  60. package/lib/job.d.ts +64 -0
  61. package/lib/job.js +101 -0
  62. package/lib/namespace.d.ts +128 -0
  63. package/lib/namespace.js +148 -0
  64. package/lib/network-policy.d.ts +311 -0
  65. package/lib/network-policy.js +383 -0
  66. package/lib/pod.d.ts +1097 -0
  67. package/lib/pod.js +1227 -0
  68. package/lib/probe.d.ts +181 -0
  69. package/lib/probe.js +124 -0
  70. package/lib/pv.d.ts +375 -0
  71. package/lib/pv.js +387 -0
  72. package/lib/pvc.d.ts +163 -0
  73. package/lib/pvc.js +204 -0
  74. package/lib/role-binding.d.ts +138 -0
  75. package/lib/role-binding.js +207 -0
  76. package/lib/role.d.ts +268 -0
  77. package/lib/role.js +441 -0
  78. package/lib/secret.d.ts +195 -0
  79. package/lib/secret.js +221 -0
  80. package/lib/service-account.d.ts +83 -0
  81. package/lib/service-account.js +148 -0
  82. package/lib/service.d.ts +289 -0
  83. package/lib/service.js +235 -0
  84. package/lib/stateful-set.d.ts +206 -0
  85. package/lib/stateful-set.js +291 -0
  86. package/lib/utils.d.ts +4 -0
  87. package/lib/utils.js +33 -0
  88. package/lib/volume.d.ts +577 -0
  89. package/lib/volume.js +410 -0
  90. package/lib/workload.d.ts +121 -0
  91. package/lib/workload.js +158 -0
  92. package/node_modules/balanced-match/.github/FUNDING.yml +2 -0
  93. package/node_modules/balanced-match/LICENSE.md +21 -0
  94. package/node_modules/balanced-match/README.md +97 -0
  95. package/node_modules/balanced-match/index.js +62 -0
  96. package/node_modules/balanced-match/package.json +48 -0
  97. package/node_modules/brace-expansion/.github/FUNDING.yml +2 -0
  98. package/node_modules/brace-expansion/LICENSE +21 -0
  99. package/node_modules/brace-expansion/README.md +157 -0
  100. package/node_modules/brace-expansion/index.js +394 -0
  101. package/node_modules/brace-expansion/package.json +49 -0
  102. package/node_modules/minimatch/LICENSE +15 -0
  103. package/node_modules/minimatch/README.md +491 -0
  104. package/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +2 -0
  105. package/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts.map +1 -0
  106. package/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js +14 -0
  107. package/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js.map +1 -0
  108. package/node_modules/minimatch/dist/commonjs/ast.d.ts +20 -0
  109. package/node_modules/minimatch/dist/commonjs/ast.d.ts.map +1 -0
  110. package/node_modules/minimatch/dist/commonjs/ast.js +747 -0
  111. package/node_modules/minimatch/dist/commonjs/ast.js.map +1 -0
  112. package/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts +8 -0
  113. package/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +1 -0
  114. package/node_modules/minimatch/dist/commonjs/brace-expressions.js +152 -0
  115. package/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +1 -0
  116. package/node_modules/minimatch/dist/commonjs/escape.d.ts +12 -0
  117. package/node_modules/minimatch/dist/commonjs/escape.d.ts.map +1 -0
  118. package/node_modules/minimatch/dist/commonjs/escape.js +22 -0
  119. package/node_modules/minimatch/dist/commonjs/escape.js.map +1 -0
  120. package/node_modules/minimatch/dist/commonjs/index.d.ts +98 -0
  121. package/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -0
  122. package/node_modules/minimatch/dist/commonjs/index.js +1023 -0
  123. package/node_modules/minimatch/dist/commonjs/index.js.map +1 -0
  124. package/node_modules/minimatch/dist/commonjs/package.json +3 -0
  125. package/node_modules/minimatch/dist/commonjs/unescape.d.ts +17 -0
  126. package/node_modules/minimatch/dist/commonjs/unescape.d.ts.map +1 -0
  127. package/node_modules/minimatch/dist/commonjs/unescape.js +24 -0
  128. package/node_modules/minimatch/dist/commonjs/unescape.js.map +1 -0
  129. package/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +2 -0
  130. package/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts.map +1 -0
  131. package/node_modules/minimatch/dist/esm/assert-valid-pattern.js +10 -0
  132. package/node_modules/minimatch/dist/esm/assert-valid-pattern.js.map +1 -0
  133. package/node_modules/minimatch/dist/esm/ast.d.ts +20 -0
  134. package/node_modules/minimatch/dist/esm/ast.d.ts.map +1 -0
  135. package/node_modules/minimatch/dist/esm/ast.js +743 -0
  136. package/node_modules/minimatch/dist/esm/ast.js.map +1 -0
  137. package/node_modules/minimatch/dist/esm/brace-expressions.d.ts +8 -0
  138. package/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +1 -0
  139. package/node_modules/minimatch/dist/esm/brace-expressions.js +148 -0
  140. package/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -0
  141. package/node_modules/minimatch/dist/esm/escape.d.ts +12 -0
  142. package/node_modules/minimatch/dist/esm/escape.d.ts.map +1 -0
  143. package/node_modules/minimatch/dist/esm/escape.js +18 -0
  144. package/node_modules/minimatch/dist/esm/escape.js.map +1 -0
  145. package/node_modules/minimatch/dist/esm/index.d.ts +98 -0
  146. package/node_modules/minimatch/dist/esm/index.d.ts.map +1 -0
  147. package/node_modules/minimatch/dist/esm/index.js +1007 -0
  148. package/node_modules/minimatch/dist/esm/index.js.map +1 -0
  149. package/node_modules/minimatch/dist/esm/package.json +3 -0
  150. package/node_modules/minimatch/dist/esm/unescape.d.ts +17 -0
  151. package/node_modules/minimatch/dist/esm/unescape.d.ts.map +1 -0
  152. package/node_modules/minimatch/dist/esm/unescape.js +20 -0
  153. package/node_modules/minimatch/dist/esm/unescape.js.map +1 -0
  154. package/node_modules/minimatch/package.json +82 -0
  155. package/package.json +172 -6
  156. package/rotate.md +82 -0
package/lib/pod.js ADDED
@@ -0,0 +1,1227 @@
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.PodConnections = exports.PodConnectionsIsolation = exports.PodScheduling = exports.Topology = exports.Node = exports.NamedNode = exports.TaintedNode = exports.LabeledNode = exports.Pods = exports.NodeTaintQuery = exports.TaintEffect = exports.LabelExpression = exports.NodeLabelQuery = exports.DnsPolicy = exports.FsGroupChangePolicy = exports.RestartPolicy = exports.PodSecurityContext = exports.PodDns = exports.Pod = exports.LabelSelector = exports.AbstractPod = void 0;
37
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
38
+ const cdk8s_1 = require("cdk8s");
39
+ const constructs_1 = require("constructs");
40
+ const base = __importStar(require("./base"));
41
+ const container = __importStar(require("./container"));
42
+ const k8s = __importStar(require("./imports/k8s"));
43
+ const networkpolicy = __importStar(require("./network-policy"));
44
+ const utils_1 = require("./utils");
45
+ class AbstractPod extends base.Resource {
46
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.AbstractPod", version: "2.0.0" };
47
+ restartPolicy;
48
+ serviceAccount;
49
+ securityContext;
50
+ dns;
51
+ dockerRegistryAuth;
52
+ automountServiceAccountToken;
53
+ shareProcessNamespace;
54
+ hostNetwork;
55
+ terminationGracePeriod;
56
+ enableServiceLinks;
57
+ isolate;
58
+ _containers = [];
59
+ _initContainers = [];
60
+ _hostAliases = [];
61
+ _volumes = new Map();
62
+ constructor(scope, id, props = {}) {
63
+ super(scope, id);
64
+ this.restartPolicy = props.restartPolicy ?? RestartPolicy.ALWAYS;
65
+ this.serviceAccount = props.serviceAccount;
66
+ this.securityContext = new PodSecurityContext(props.securityContext);
67
+ this.dns = new PodDns(props.dns);
68
+ this.dockerRegistryAuth = props.dockerRegistryAuth;
69
+ this.automountServiceAccountToken = props.automountServiceAccountToken ?? false;
70
+ this.shareProcessNamespace = props.shareProcessNamespace ?? false;
71
+ this.isolate = props.isolate ?? false;
72
+ this.hostNetwork = props.hostNetwork ?? false;
73
+ this.terminationGracePeriod = props.terminationGracePeriod ?? cdk8s_1.Duration.seconds(30);
74
+ this.enableServiceLinks = props.enableServiceLinks;
75
+ if (props.containers) {
76
+ props.containers.forEach(c => this.addContainer(c));
77
+ }
78
+ if (props.volumes) {
79
+ props.volumes.forEach(v => this.addVolume(v));
80
+ }
81
+ if (props.initContainers) {
82
+ props.initContainers.forEach(c => this.addInitContainer(c));
83
+ }
84
+ if (props.hostAliases) {
85
+ props.hostAliases.forEach(c => this.addHostAlias(c));
86
+ }
87
+ }
88
+ get containers() {
89
+ return [...this._containers];
90
+ }
91
+ get initContainers() {
92
+ return [...this._initContainers];
93
+ }
94
+ get volumes() {
95
+ return Array.from(this._volumes.values());
96
+ }
97
+ get hostAliases() {
98
+ return [...this._hostAliases];
99
+ }
100
+ /**
101
+ * @see IPodSelector.toPodSelectorConfig()
102
+ */
103
+ toPodSelectorConfig() {
104
+ const podAddress = this.podMetadata.getLabel(Pod.ADDRESS_LABEL);
105
+ if (!podAddress) {
106
+ // shouldn't happen because we add this label automatically in both pods and workloads.
107
+ throw new Error(`Unable to create a label selector since ${Pod.ADDRESS_LABEL} label is missing`);
108
+ }
109
+ return {
110
+ labelSelector: LabelSelector.of({ labels: { [Pod.ADDRESS_LABEL]: podAddress } }),
111
+ namespaces: this.metadata.namespace ? {
112
+ names: [this.metadata.namespace],
113
+ } : undefined,
114
+ };
115
+ }
116
+ /**
117
+ * @see INetworkPolicyPeer.toNetworkPolicyPeerConfig()
118
+ */
119
+ toNetworkPolicyPeerConfig() {
120
+ return { podSelector: this.toPodSelectorConfig() };
121
+ }
122
+ /**
123
+ * @see INetworkPolicyPeer.toPodSelector()
124
+ */
125
+ toPodSelector() {
126
+ return this;
127
+ }
128
+ addContainer(cont) {
129
+ const impl = new container.Container(cont);
130
+ this.attachContainer(impl);
131
+ return impl;
132
+ }
133
+ attachContainer(cont) {
134
+ this._containers.push(cont);
135
+ }
136
+ addInitContainer(cont) {
137
+ // https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#differences-from-regular-containers
138
+ if (!this.isSidecarContainer(cont) && cont.readiness) {
139
+ throw new Error('Init containers must not have a readiness probe');
140
+ }
141
+ if (!this.isSidecarContainer(cont) && cont.liveness) {
142
+ throw new Error('Init containers must not have a liveness probe');
143
+ }
144
+ if (!this.isSidecarContainer(cont) && cont.startup) {
145
+ throw new Error('Init containers must not have a startup probe');
146
+ }
147
+ const impl = new container.Container({
148
+ ...cont,
149
+ name: cont.name ?? `init-${this._initContainers.length}`,
150
+ });
151
+ this._initContainers.push(impl);
152
+ return impl;
153
+ }
154
+ // Any initContainer that has `restartPolicy=Always` is a sidecar container. Please refer to
155
+ // documentation for more details:
156
+ // https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/#differences-from-init-containers
157
+ isSidecarContainer(cont) {
158
+ return cont.restartPolicy === container.ContainerRestartPolicy.ALWAYS;
159
+ }
160
+ addHostAlias(hostAlias) {
161
+ this._hostAliases.push(hostAlias);
162
+ }
163
+ addVolume(vol) {
164
+ const existingVolume = this._volumes.get(vol.name);
165
+ if (existingVolume) {
166
+ throw new Error(`Volume with name ${vol.name} already exists`);
167
+ }
168
+ this._volumes.set(vol.name, vol);
169
+ }
170
+ /**
171
+ * @see ISubect.toSubjectConfiguration()
172
+ */
173
+ toSubjectConfiguration() {
174
+ if (!this.serviceAccount && !this.automountServiceAccountToken) {
175
+ throw new Error(`${this.name} cannot be converted to a role binding subject:`
176
+ + ' You must either assign a service account to it, or use \'automountServiceAccountToken: true\'');
177
+ }
178
+ // 'default' is assumed to be the name of the default service account
179
+ // in the cluster.
180
+ const serviceAccountName = this.serviceAccount?.name ?? 'default';
181
+ return {
182
+ kind: 'ServiceAccount',
183
+ name: serviceAccountName,
184
+ apiGroup: '',
185
+ };
186
+ }
187
+ /**
188
+ * @internal
189
+ */
190
+ _toPodSpec() {
191
+ if (this.containers.length === 0) {
192
+ throw new Error('PodSpec must have at least 1 container');
193
+ }
194
+ const volumes = new Map();
195
+ const containers = [];
196
+ const initContainers = [];
197
+ for (const cont of this.containers) {
198
+ // check if restartPolicy is defined for containers
199
+ if (cont.restartPolicy) {
200
+ throw new Error(`Invalid container spec: ${cont.name} has non-empty restartPolicy field. The field can only be specified for initContainers`);
201
+ }
202
+ // automatically add volume from the container mount
203
+ // to this pod so thats its available to the container.
204
+ for (const mount of cont.mounts) {
205
+ addVolume(mount.volume);
206
+ }
207
+ containers.push(cont._toKube());
208
+ }
209
+ for (const cont of this.initContainers) {
210
+ // automatically add volume from the container mount
211
+ // to this pod so thats its available to the container.
212
+ for (const mount of cont.mounts) {
213
+ addVolume(mount.volume);
214
+ }
215
+ initContainers.push(cont._toKube());
216
+ }
217
+ for (const vol of this.volumes) {
218
+ addVolume(vol);
219
+ }
220
+ function addVolume(vol) {
221
+ const existingVolume = volumes.get(vol.name);
222
+ // its ok to call this function twice on the same volume, but its not ok to
223
+ // call it twice on a different volume with the same name.
224
+ if (existingVolume && existingVolume !== vol) {
225
+ throw new Error(`Invalid mount configuration. At least two different volumes have the same name: ${vol.name}`);
226
+ }
227
+ volumes.set(vol.name, vol);
228
+ }
229
+ const dns = this.dns._toKube();
230
+ return {
231
+ restartPolicy: this.restartPolicy,
232
+ serviceAccountName: this.serviceAccount?.name,
233
+ containers: containers,
234
+ securityContext: (0, utils_1.undefinedIfEmpty)(this.securityContext._toKube()),
235
+ initContainers: (0, utils_1.undefinedIfEmpty)(initContainers),
236
+ hostAliases: (0, utils_1.undefinedIfEmpty)(this.hostAliases),
237
+ volumes: (0, utils_1.undefinedIfEmpty)(Array.from(volumes.values()).map(v => v._toKube())),
238
+ dnsPolicy: dns.policy,
239
+ dnsConfig: (0, utils_1.undefinedIfEmpty)(dns.config),
240
+ hostname: dns.hostname,
241
+ subdomain: dns.subdomain,
242
+ setHostnameAsFqdn: dns.hostnameAsFQDN,
243
+ imagePullSecrets: this.dockerRegistryAuth ? [{ name: this.dockerRegistryAuth.name }] : undefined,
244
+ automountServiceAccountToken: this.automountServiceAccountToken,
245
+ shareProcessNamespace: this.shareProcessNamespace,
246
+ hostNetwork: this.hostNetwork,
247
+ terminationGracePeriodSeconds: this.terminationGracePeriod?.toSeconds(),
248
+ enableServiceLinks: this.enableServiceLinks,
249
+ };
250
+ }
251
+ }
252
+ exports.AbstractPod = AbstractPod;
253
+ /**
254
+ * Match a resource by labels.
255
+ */
256
+ class LabelSelector {
257
+ expressions;
258
+ labels;
259
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.LabelSelector", version: "2.0.0" };
260
+ static of(options = {}) {
261
+ return new LabelSelector(options.expressions ?? [], options.labels ?? {});
262
+ }
263
+ constructor(expressions, labels) {
264
+ this.expressions = expressions;
265
+ this.labels = labels;
266
+ }
267
+ isEmpty() {
268
+ return this.expressions.length === 0 && Object.keys(this.labels).length === 0;
269
+ }
270
+ /**
271
+ * @internal
272
+ */
273
+ _toKube() {
274
+ if (this.isEmpty()) {
275
+ return {};
276
+ }
277
+ return {
278
+ matchExpressions: (0, utils_1.undefinedIfEmpty)(this.expressions.map(q => ({
279
+ key: q.key,
280
+ operator: q.operator,
281
+ values: q.values,
282
+ }))),
283
+ matchLabels: (0, utils_1.undefinedIfEmpty)(this.labels),
284
+ };
285
+ }
286
+ }
287
+ exports.LabelSelector = LabelSelector;
288
+ /**
289
+ * Pod is a collection of containers that can run on a host. This resource is
290
+ * created by clients and scheduled onto hosts.
291
+ */
292
+ class Pod extends AbstractPod {
293
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.Pod", version: "2.0.0" };
294
+ /**
295
+ * This label is autoamtically added by cdk8s to any pod. It provides
296
+ * a unique and stable identifier for the pod.
297
+ */
298
+ static ADDRESS_LABEL = 'cdk8s.io/metadata.addr';
299
+ /**
300
+ * @see base.Resource.apiObject
301
+ */
302
+ apiObject;
303
+ resourceType = 'pods';
304
+ scheduling;
305
+ connections;
306
+ constructor(scope, id, props = {}) {
307
+ super(scope, id, props);
308
+ this.apiObject = new k8s.KubePod(this, 'Resource', {
309
+ metadata: props.metadata,
310
+ spec: cdk8s_1.Lazy.any({ produce: () => this._toKube() }),
311
+ });
312
+ this.metadata.addLabel(Pod.ADDRESS_LABEL, cdk8s_1.Names.toLabelValue(this));
313
+ this.scheduling = new PodScheduling(this);
314
+ this.connections = new PodConnections(this);
315
+ if (this.isolate) {
316
+ this.connections.isolate();
317
+ }
318
+ }
319
+ get podMetadata() {
320
+ return this.metadata;
321
+ }
322
+ /**
323
+ * @internal
324
+ */
325
+ _toKube() {
326
+ const scheduling = this.scheduling._toKube();
327
+ return {
328
+ ...this._toPodSpec(),
329
+ affinity: scheduling.affinity,
330
+ nodeName: scheduling.nodeName,
331
+ tolerations: scheduling.tolerations,
332
+ };
333
+ }
334
+ }
335
+ exports.Pod = Pod;
336
+ /**
337
+ * Holds dns settings of the pod.
338
+ */
339
+ class PodDns {
340
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.PodDns", version: "2.0.0" };
341
+ /**
342
+ * The DNS policy of this pod.
343
+ */
344
+ policy;
345
+ /**
346
+ * The configured hostname of the pod. Undefined means its set to a system-defined value.
347
+ */
348
+ hostname;
349
+ /**
350
+ * The configured subdomain of the pod.
351
+ */
352
+ subdomain;
353
+ /**
354
+ * Whether or not the pods hostname is set to its FQDN.
355
+ */
356
+ hostnameAsFQDN;
357
+ _nameservers;
358
+ _searches;
359
+ _options;
360
+ constructor(props = {}) {
361
+ this.hostname = props.hostname;
362
+ this.subdomain = props.subdomain;
363
+ this.policy = props.policy ?? DnsPolicy.CLUSTER_FIRST;
364
+ this.hostnameAsFQDN = props.hostnameAsFQDN ?? false;
365
+ this._nameservers = props.nameservers ?? [];
366
+ this._searches = props.searches ?? [];
367
+ this._options = props.options ?? [];
368
+ }
369
+ /**
370
+ * Nameservers defined for this pod.
371
+ */
372
+ get nameservers() {
373
+ return [...this._nameservers];
374
+ }
375
+ /**
376
+ * Search domains defined for this pod.
377
+ */
378
+ get searches() {
379
+ return [...this._searches];
380
+ }
381
+ /**
382
+ * Custom dns options defined for this pod.
383
+ */
384
+ get options() {
385
+ return [...this._options];
386
+ }
387
+ /**
388
+ * Add a nameserver.
389
+ */
390
+ addNameserver(...nameservers) {
391
+ this._nameservers.push(...nameservers);
392
+ }
393
+ /**
394
+ * Add a search domain.
395
+ */
396
+ addSearch(...searches) {
397
+ this._searches.push(...searches);
398
+ }
399
+ /**
400
+ * Add a custom option.
401
+ */
402
+ addOption(...options) {
403
+ this._options.push(...options);
404
+ }
405
+ /**
406
+ * @internal
407
+ */
408
+ _toKube() {
409
+ if (this.policy === DnsPolicy.NONE && this.nameservers.length === 0) {
410
+ throw new Error('When dns policy is set to NONE, at least one nameserver is required');
411
+ }
412
+ if (this.nameservers.length > 3) {
413
+ throw new Error('There can be at most 3 nameservers specified');
414
+ }
415
+ if (this.searches.length > 6) {
416
+ throw new Error('There can be at most 6 search domains specified');
417
+ }
418
+ return {
419
+ hostname: this.hostname,
420
+ subdomain: this.subdomain,
421
+ hostnameAsFQDN: this.hostnameAsFQDN,
422
+ policy: this.policy,
423
+ config: {
424
+ nameservers: (0, utils_1.undefinedIfEmpty)(this.nameservers),
425
+ searches: (0, utils_1.undefinedIfEmpty)(this.searches),
426
+ options: (0, utils_1.undefinedIfEmpty)(this.options),
427
+ },
428
+ };
429
+ }
430
+ }
431
+ exports.PodDns = PodDns;
432
+ /**
433
+ * Holds pod-level security attributes and common container settings.
434
+ */
435
+ class PodSecurityContext {
436
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.PodSecurityContext", version: "2.0.0" };
437
+ ensureNonRoot;
438
+ user;
439
+ group;
440
+ fsGroup;
441
+ fsGroupChangePolicy;
442
+ _sysctls = [];
443
+ constructor(props = {}) {
444
+ this.ensureNonRoot = props.ensureNonRoot ?? true;
445
+ this.fsGroupChangePolicy = props.fsGroupChangePolicy ?? FsGroupChangePolicy.ALWAYS;
446
+ this.user = props.user;
447
+ this.group = props.group;
448
+ this.fsGroup = props.fsGroup;
449
+ for (const sysctl of props.sysctls ?? []) {
450
+ this._sysctls.push(sysctl);
451
+ }
452
+ }
453
+ get sysctls() {
454
+ return [...this._sysctls];
455
+ }
456
+ /**
457
+ * @internal
458
+ */
459
+ _toKube() {
460
+ return {
461
+ runAsGroup: this.group,
462
+ runAsUser: this.user,
463
+ fsGroup: this.fsGroup,
464
+ runAsNonRoot: this.ensureNonRoot,
465
+ fsGroupChangePolicy: this.fsGroupChangePolicy,
466
+ sysctls: (0, utils_1.undefinedIfEmpty)(this._sysctls),
467
+ };
468
+ }
469
+ }
470
+ exports.PodSecurityContext = PodSecurityContext;
471
+ /**
472
+ * Restart policy for all containers within the pod.
473
+ */
474
+ var RestartPolicy;
475
+ (function (RestartPolicy) {
476
+ /**
477
+ * Always restart the pod after it exits.
478
+ */
479
+ RestartPolicy["ALWAYS"] = "Always";
480
+ /**
481
+ * Only restart if the pod exits with a non-zero exit code.
482
+ */
483
+ RestartPolicy["ON_FAILURE"] = "OnFailure";
484
+ /**
485
+ * Never restart the pod.
486
+ */
487
+ RestartPolicy["NEVER"] = "Never";
488
+ })(RestartPolicy || (exports.RestartPolicy = RestartPolicy = {}));
489
+ var FsGroupChangePolicy;
490
+ (function (FsGroupChangePolicy) {
491
+ /**
492
+ * Only change permissions and ownership if permission and ownership of root directory does
493
+ * not match with expected permissions of the volume.
494
+ * This could help shorten the time it takes to change ownership and permission of a volume
495
+ */
496
+ FsGroupChangePolicy["ON_ROOT_MISMATCH"] = "OnRootMismatch";
497
+ /**
498
+ * Always change permission and ownership of the volume when volume is mounted.
499
+ */
500
+ FsGroupChangePolicy["ALWAYS"] = "Always";
501
+ })(FsGroupChangePolicy || (exports.FsGroupChangePolicy = FsGroupChangePolicy = {}));
502
+ /**
503
+ * Pod DNS policies.
504
+ */
505
+ var DnsPolicy;
506
+ (function (DnsPolicy) {
507
+ /**
508
+ * Any DNS query that does not match the configured cluster domain suffix,
509
+ * such as "www.kubernetes.io", is forwarded to the
510
+ * upstream nameserver inherited from the node.
511
+ * Cluster administrators may have extra stub-domain and upstream DNS servers configured.
512
+ */
513
+ DnsPolicy["CLUSTER_FIRST"] = "ClusterFirst";
514
+ /**
515
+ * For Pods running with hostNetwork, you should
516
+ * explicitly set its DNS policy "ClusterFirstWithHostNet".
517
+ */
518
+ DnsPolicy["CLUSTER_FIRST_WITH_HOST_NET"] = "ClusterFirstWithHostNet";
519
+ /**
520
+ * The Pod inherits the name resolution configuration
521
+ * from the node that the pods run on.
522
+ */
523
+ DnsPolicy["DEFAULT"] = "Default";
524
+ /**
525
+ * It allows a Pod to ignore DNS settings from the Kubernetes environment.
526
+ * All DNS settings are supposed to be provided using the dnsConfig
527
+ * field in the Pod Spec.
528
+ */
529
+ DnsPolicy["NONE"] = "None";
530
+ })(DnsPolicy || (exports.DnsPolicy = DnsPolicy = {}));
531
+ /**
532
+ * Represents a query that can be performed against nodes with labels.
533
+ */
534
+ class NodeLabelQuery {
535
+ key;
536
+ operator;
537
+ values;
538
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.NodeLabelQuery", version: "2.0.0" };
539
+ /**
540
+ * Requires value of label `key` to equal `value`.
541
+ */
542
+ static is(key, value) {
543
+ return NodeLabelQuery.in(key, [value]);
544
+ }
545
+ /**
546
+ * Requires value of label `key` to be one of `values`.
547
+ */
548
+ static in(key, values) {
549
+ return new NodeLabelQuery(key, 'In', values);
550
+ }
551
+ /**
552
+ * Requires value of label `key` to be none of `values`.
553
+ */
554
+ static notIn(key, values) {
555
+ return new NodeLabelQuery(key, 'NotIn', values);
556
+ }
557
+ /**
558
+ * Requires label `key` to exist.
559
+ */
560
+ static exists(key) {
561
+ return new NodeLabelQuery(key, 'Exists', undefined);
562
+ }
563
+ /**
564
+ * Requires label `key` to not exist.
565
+ */
566
+ static doesNotExist(key) {
567
+ return new NodeLabelQuery(key, 'DoesNotExist', undefined);
568
+ }
569
+ /**
570
+ * Requires value of label `key` to greater than all elements in `values`.
571
+ */
572
+ static gt(key, values) {
573
+ return new NodeLabelQuery(key, 'Gt', values);
574
+ }
575
+ /**
576
+ * Requires value of label `key` to less than all elements in `values`.
577
+ */
578
+ static lt(key, values) {
579
+ return new NodeLabelQuery(key, 'Lt', values);
580
+ }
581
+ constructor(key, operator, values) {
582
+ this.key = key;
583
+ this.operator = operator;
584
+ this.values = values;
585
+ }
586
+ /**
587
+ * @internal
588
+ */
589
+ _toKube() {
590
+ return {
591
+ key: this.key,
592
+ operator: this.operator,
593
+ values: this.values,
594
+ };
595
+ }
596
+ }
597
+ exports.NodeLabelQuery = NodeLabelQuery;
598
+ /**
599
+ * Represents a query that can be performed against resources with labels.
600
+ */
601
+ class LabelExpression {
602
+ key;
603
+ operator;
604
+ values;
605
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.LabelExpression", version: "2.0.0" };
606
+ /**
607
+ * Requires value of label `key` to be one of `values`.
608
+ */
609
+ static in(key, values) {
610
+ return new LabelExpression(key, 'In', values);
611
+ }
612
+ /**
613
+ * Requires value of label `key` to be none of `values`.
614
+ */
615
+ static notIn(key, values) {
616
+ return new LabelExpression(key, 'NotIn', values);
617
+ }
618
+ /**
619
+ * Requires label `key` to exist.
620
+ */
621
+ static exists(key) {
622
+ return new LabelExpression(key, 'Exists', undefined);
623
+ }
624
+ /**
625
+ * Requires label `key` to not exist.
626
+ */
627
+ static doesNotExist(key) {
628
+ return new LabelExpression(key, 'DoesNotExist', undefined);
629
+ }
630
+ constructor(key, operator, values) {
631
+ this.key = key;
632
+ this.operator = operator;
633
+ this.values = values;
634
+ }
635
+ }
636
+ exports.LabelExpression = LabelExpression;
637
+ /**
638
+ * Taint effects.
639
+ */
640
+ var TaintEffect;
641
+ (function (TaintEffect) {
642
+ /**
643
+ * This means that no pod will be able to schedule
644
+ * onto the node unless it has a matching toleration.
645
+ */
646
+ TaintEffect["NO_SCHEDULE"] = "NoSchedule";
647
+ /**
648
+ * This is a "preference" or "soft" version of `NO_SCHEDULE` -- the system
649
+ * will try to avoid placing a pod that does not tolerate the taint on the node,
650
+ * but it is not required
651
+ */
652
+ TaintEffect["PREFER_NO_SCHEDULE"] = "PreferNoSchedule";
653
+ /**
654
+ * This affects pods that are already running on the node as follows:
655
+ *
656
+ * - Pods that do not tolerate the taint are evicted immediately.
657
+ * - Pods that tolerate the taint without specifying `duration` remain bound forever.
658
+ * - Pods that tolerate the taint with a specified `duration` remain bound for
659
+ * the specified amount of time.
660
+ */
661
+ TaintEffect["NO_EXECUTE"] = "NoExecute";
662
+ })(TaintEffect || (exports.TaintEffect = TaintEffect = {}));
663
+ /**
664
+ * Taint queries that can be perfomed against nodes.
665
+ */
666
+ class NodeTaintQuery {
667
+ operator;
668
+ key;
669
+ value;
670
+ effect;
671
+ evictAfter;
672
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.NodeTaintQuery", version: "2.0.0" };
673
+ /**
674
+ * Matches a taint with a specific key and value.
675
+ */
676
+ static is(key, value, options = {}) {
677
+ return new NodeTaintQuery('Equal', key, value, options.effect, options.evictAfter);
678
+ }
679
+ /**
680
+ * Matches a tain with any value of a specific key.
681
+ */
682
+ static exists(key, options = {}) {
683
+ return new NodeTaintQuery('Exists', key, undefined, options.effect, options.evictAfter);
684
+ }
685
+ /**
686
+ * Matches any taint.
687
+ */
688
+ static any() {
689
+ return new NodeTaintQuery('Exists');
690
+ }
691
+ constructor(operator, key, value, effect, evictAfter) {
692
+ this.operator = operator;
693
+ this.key = key;
694
+ this.value = value;
695
+ this.effect = effect;
696
+ this.evictAfter = evictAfter;
697
+ if (evictAfter && effect !== TaintEffect.NO_EXECUTE) {
698
+ throw new Error('Only \'NO_EXECUTE\' effects can specify \'evictAfter\'');
699
+ }
700
+ }
701
+ /**
702
+ * @internal
703
+ */
704
+ _toKube() {
705
+ return {
706
+ effect: this.effect,
707
+ key: this.key,
708
+ operator: this.operator,
709
+ tolerationSeconds: this.evictAfter?.toSeconds(),
710
+ value: this.value,
711
+ };
712
+ }
713
+ }
714
+ exports.NodeTaintQuery = NodeTaintQuery;
715
+ /**
716
+ * Represents a group of pods.
717
+ */
718
+ class Pods extends constructs_1.Construct {
719
+ expressions;
720
+ labels;
721
+ namespaces;
722
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.Pods", version: "2.0.0" };
723
+ /**
724
+ * Select pods in the cluster with various selectors.
725
+ */
726
+ static select(scope, id, options) {
727
+ return new Pods(scope, id, options.expressions, options.labels, options.namespaces);
728
+ }
729
+ /**
730
+ * Select all pods.
731
+ */
732
+ static all(scope, id, options = {}) {
733
+ return Pods.select(scope, id, { namespaces: options.namespaces });
734
+ }
735
+ constructor(scope, id, expressions, labels, namespaces) {
736
+ super(scope, id);
737
+ this.expressions = expressions;
738
+ this.labels = labels;
739
+ this.namespaces = namespaces;
740
+ }
741
+ /**
742
+ * @see IPodSelector.toPodSelectorConfig()
743
+ */
744
+ toPodSelectorConfig() {
745
+ return {
746
+ labelSelector: LabelSelector.of({ expressions: this.expressions, labels: this.labels }),
747
+ namespaces: this.namespaces?.toNamespaceSelectorConfig(),
748
+ };
749
+ }
750
+ /**
751
+ * @see INetworkPolicyPeer.toNetworkPolicyPeerConfig()
752
+ */
753
+ toNetworkPolicyPeerConfig() {
754
+ return { podSelector: this.toPodSelectorConfig() };
755
+ }
756
+ /**
757
+ * @see INetworkPolicyPeer.toPodSelector()
758
+ */
759
+ toPodSelector() {
760
+ return this;
761
+ }
762
+ }
763
+ exports.Pods = Pods;
764
+ /**
765
+ * A node that is matched by label selectors.
766
+ */
767
+ class LabeledNode {
768
+ labelSelector;
769
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.LabeledNode", version: "2.0.0" };
770
+ constructor(labelSelector) {
771
+ this.labelSelector = labelSelector;
772
+ }
773
+ ;
774
+ }
775
+ exports.LabeledNode = LabeledNode;
776
+ /**
777
+ * A node that is matched by taint selectors.
778
+ */
779
+ class TaintedNode {
780
+ taintSelector;
781
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.TaintedNode", version: "2.0.0" };
782
+ constructor(taintSelector) {
783
+ this.taintSelector = taintSelector;
784
+ }
785
+ ;
786
+ }
787
+ exports.TaintedNode = TaintedNode;
788
+ /**
789
+ * A node that is matched by its name.
790
+ */
791
+ class NamedNode {
792
+ name;
793
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.NamedNode", version: "2.0.0" };
794
+ constructor(name) {
795
+ this.name = name;
796
+ }
797
+ ;
798
+ }
799
+ exports.NamedNode = NamedNode;
800
+ /**
801
+ * Represents a node in the cluster.
802
+ */
803
+ class Node {
804
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.Node", version: "2.0.0" };
805
+ /**
806
+ * Match a node by its labels.
807
+ */
808
+ static labeled(...labelSelector) {
809
+ return new LabeledNode(labelSelector);
810
+ }
811
+ /**
812
+ * Match a node by its name.
813
+ */
814
+ static named(nodeName) {
815
+ return new NamedNode(nodeName);
816
+ }
817
+ /**
818
+ * Match a node by its taints.
819
+ */
820
+ static tainted(...taintSelector) {
821
+ return new TaintedNode(taintSelector);
822
+ }
823
+ }
824
+ exports.Node = Node;
825
+ /**
826
+ * Available topology domains.
827
+ */
828
+ class Topology {
829
+ key;
830
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.Topology", version: "2.0.0" };
831
+ /**
832
+ * A hostname represents a single node in the cluster.
833
+ *
834
+ * @see https://kubernetes.io/docs/reference/labels-annotations-taints/#kubernetesiohostname
835
+ */
836
+ static HOSTNAME = new Topology('kubernetes.io/hostname');
837
+ /**
838
+ * A zone represents a logical failure domain. It is common for Kubernetes clusters to
839
+ * span multiple zones for increased availability. While the exact definition of a zone is
840
+ * left to infrastructure implementations, common properties of a zone include very low
841
+ * network latency within a zone, no-cost network traffic within a zone, and failure
842
+ * independence from other zones. For example, nodes within a zone might share a network
843
+ * switch, but nodes in different zones should not.
844
+ *
845
+ * @see https://kubernetes.io/docs/reference/labels-annotations-taints/#topologykubernetesiozone
846
+ */
847
+ static ZONE = new Topology('topology.kubernetes.io/zone');
848
+ /**
849
+ * A region represents a larger domain, made up of one or more zones. It is uncommon
850
+ * for Kubernetes clusters to span multiple regions. While the exact definition of a
851
+ * zone or region is left to infrastructure implementations, common properties of a region
852
+ * include higher network latency between them than within them, non-zero cost for network
853
+ * traffic between them, and failure independence from other zones or regions.
854
+ *
855
+ * For example, nodes within a region might share power infrastructure (e.g. a UPS or generator), but
856
+ * nodes in different regions typically would not.
857
+ *
858
+ * @see https://kubernetes.io/docs/reference/labels-annotations-taints/#topologykubernetesioregion
859
+ */
860
+ static REGION = new Topology('topology.kubernetes.io/region');
861
+ /**
862
+ * Custom key for the node label that the system uses to denote the topology domain.
863
+ */
864
+ static custom(key) {
865
+ return new Topology(key);
866
+ }
867
+ constructor(key) {
868
+ this.key = key;
869
+ }
870
+ ;
871
+ }
872
+ exports.Topology = Topology;
873
+ /**
874
+ * Controls the pod scheduling strategy.
875
+ */
876
+ class PodScheduling {
877
+ instance;
878
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.PodScheduling", version: "2.0.0" };
879
+ _nodeAffinityPreferred = [];
880
+ _nodeAffinityRequired = [];
881
+ _podAffinityPreferred = [];
882
+ _podAffinityRequired = [];
883
+ _podAntiAffinityPreferred = [];
884
+ _podAntiAffinityRequired = [];
885
+ _tolerations = [];
886
+ _nodeName;
887
+ constructor(instance) {
888
+ this.instance = instance;
889
+ }
890
+ /**
891
+ * Assign this pod a specific node by name.
892
+ *
893
+ * The scheduler ignores the Pod, and the kubelet on the named node
894
+ * tries to place the Pod on that node. Overrules any affinity rules of the pod.
895
+ *
896
+ * Some limitations of static assignment are:
897
+ *
898
+ * - If the named node does not exist, the Pod will not run, and in some
899
+ * cases may be automatically deleted.
900
+ * - If the named node does not have the resources to accommodate the Pod,
901
+ * the Pod will fail and its reason will indicate why, for example OutOfmemory or OutOfcpu.
902
+ * - Node names in cloud environments are not always predictable or stable.
903
+ *
904
+ * Will throw is the pod is already assigned to named node.
905
+ *
906
+ * Under the hood, this method utilizes the `nodeName` property.
907
+ */
908
+ assign(node) {
909
+ if (this._nodeName) {
910
+ // disallow overriding an static node assignment
911
+ throw new Error(`Cannot assign ${this.instance.podMetadata.name} to node ${node.name}. It is already assigned to node ${this._nodeName}`);
912
+ }
913
+ else {
914
+ this._nodeName = node.name;
915
+ }
916
+ }
917
+ /**
918
+ * Allow this pod to tolerate taints matching these tolerations.
919
+ *
920
+ * You can put multiple taints on the same node and multiple tolerations on the same pod.
921
+ * The way Kubernetes processes multiple taints and tolerations is like a filter: start with
922
+ * all of a node's taints, then ignore the ones for which the pod has a matching toleration;
923
+ * the remaining un-ignored taints have the indicated effects on the pod. In particular:
924
+ *
925
+ * - if there is at least one un-ignored taint with effect NoSchedule then Kubernetes will
926
+ * not schedule the pod onto that node
927
+ * - if there is no un-ignored taint with effect NoSchedule but there is at least one un-ignored
928
+ * taint with effect PreferNoSchedule then Kubernetes will try to not schedule the pod onto the node
929
+ * - if there is at least one un-ignored taint with effect NoExecute then the pod will be evicted from
930
+ * the node (if it is already running on the node), and will not be scheduled onto the node (if it is
931
+ * not yet running on the node).
932
+ *
933
+ * Under the hood, this method utilizes the `tolerations` property.
934
+ *
935
+ * @see https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
936
+ */
937
+ tolerate(node) {
938
+ for (const query of node.taintSelector) {
939
+ this._tolerations.push(query._toKube());
940
+ }
941
+ }
942
+ /**
943
+ * Attract this pod to a node matched by selectors.
944
+ * You can select a node by using `Node.labeled()`.
945
+ *
946
+ * Attracting to multiple nodes (i.e invoking this method multiple times) acts as
947
+ * an OR condition, meaning the pod will be assigned to either one of the nodes.
948
+ *
949
+ * Under the hood, this method utilizes the `nodeAffinity` property.
950
+ *
951
+ * @see https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity
952
+ */
953
+ attract(node, options = {}) {
954
+ const term = this.createNodeAffinityTerm(node);
955
+ if (options.weight) {
956
+ this.validateWeight(options.weight);
957
+ this._nodeAffinityPreferred.push({ weight: options.weight, preference: term });
958
+ }
959
+ else {
960
+ this._nodeAffinityRequired.push(term);
961
+ }
962
+ }
963
+ /**
964
+ * Co-locate this pod with a scheduling selection.
965
+ *
966
+ * A selection can be one of:
967
+ *
968
+ * - An instance of a `Pod`.
969
+ * - An instance of a `Workload` (e.g `Deployment`, `StatefulSet`).
970
+ * - An un-managed pod that can be selected via `Pods.select()`.
971
+ *
972
+ * Co-locating with multiple selections ((i.e invoking this method multiple times)) acts as
973
+ * an AND condition. meaning the pod will be assigned to a node that satisfies all
974
+ * selections (i.e runs at least one pod that satisifies each selection).
975
+ *
976
+ * Under the hood, this method utilizes the `podAffinity` property.
977
+ *
978
+ * @see https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity
979
+ */
980
+ colocate(selector, options = {}) {
981
+ const topology = options.topology ?? Topology.HOSTNAME;
982
+ const term = this.createPodAffinityTerm(topology, selector);
983
+ if (options.weight) {
984
+ this.validateWeight(options.weight);
985
+ this._podAffinityPreferred.push({ weight: options.weight, podAffinityTerm: term });
986
+ }
987
+ else {
988
+ this._podAffinityRequired.push(term);
989
+ }
990
+ }
991
+ /**
992
+ * Seperate this pod from a scheduling selection.
993
+ *
994
+ * A selection can be one of:
995
+ *
996
+ * - An instance of a `Pod`.
997
+ * - An instance of a `Workload` (e.g `Deployment`, `StatefulSet`).
998
+ * - An un-managed pod that can be selected via `Pods.select()`.
999
+ *
1000
+ * Seperating from multiple selections acts as an AND condition. meaning the pod
1001
+ * will not be assigned to a node that satisfies all selections (i.e runs at least one pod that satisifies each selection).
1002
+ *
1003
+ * Under the hood, this method utilizes the `podAntiAffinity` property.
1004
+ *
1005
+ * @see https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity
1006
+ */
1007
+ separate(selector, options = {}) {
1008
+ const topology = options.topology ?? Topology.HOSTNAME;
1009
+ const term = this.createPodAffinityTerm(topology, selector);
1010
+ if (options.weight) {
1011
+ this.validateWeight(options.weight);
1012
+ this._podAntiAffinityPreferred.push({ weight: options.weight, podAffinityTerm: term });
1013
+ }
1014
+ else {
1015
+ this._podAntiAffinityRequired.push(term);
1016
+ }
1017
+ }
1018
+ createPodAffinityTerm(topology, selector) {
1019
+ const config = selector.toPodSelectorConfig();
1020
+ return {
1021
+ topologyKey: topology.key,
1022
+ labelSelector: config.labelSelector._toKube(),
1023
+ namespaceSelector: config.namespaces?.labelSelector?._toKube(),
1024
+ namespaces: config.namespaces?.names,
1025
+ };
1026
+ }
1027
+ createNodeAffinityTerm(node) {
1028
+ return { matchExpressions: node.labelSelector.map(s => s._toKube()) };
1029
+ }
1030
+ validateWeight(weight) {
1031
+ if (weight < 1 || weight > 100) {
1032
+ // https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity-weight
1033
+ throw new Error(`Invalid affinity weight: ${weight}. Must be in range 1-100`);
1034
+ }
1035
+ }
1036
+ /**
1037
+ * @internal
1038
+ */
1039
+ _toKube() {
1040
+ const atLeastOne = (...arrays) => {
1041
+ return arrays.flat().length > 0;
1042
+ };
1043
+ const hasNodeAffinity = atLeastOne(this._nodeAffinityPreferred, this._nodeAffinityRequired);
1044
+ const hasPodAffinity = atLeastOne(this._podAffinityPreferred, this._podAffinityRequired);
1045
+ const hasPodAntiAffinty = atLeastOne(this._podAntiAffinityPreferred, this._podAntiAffinityRequired);
1046
+ const hasAffinity = hasNodeAffinity || hasPodAffinity || hasPodAntiAffinty;
1047
+ return {
1048
+ affinity: hasAffinity ? {
1049
+ nodeAffinity: hasNodeAffinity ? {
1050
+ preferredDuringSchedulingIgnoredDuringExecution: (0, utils_1.undefinedIfEmpty)(this._nodeAffinityPreferred),
1051
+ requiredDuringSchedulingIgnoredDuringExecution: this._nodeAffinityRequired.length > 0 ? {
1052
+ nodeSelectorTerms: this._nodeAffinityRequired,
1053
+ } : undefined,
1054
+ } : undefined,
1055
+ podAffinity: hasPodAffinity ? {
1056
+ preferredDuringSchedulingIgnoredDuringExecution: (0, utils_1.undefinedIfEmpty)(this._podAffinityPreferred),
1057
+ requiredDuringSchedulingIgnoredDuringExecution: (0, utils_1.undefinedIfEmpty)(this._podAffinityRequired),
1058
+ } : undefined,
1059
+ podAntiAffinity: hasPodAntiAffinty ? {
1060
+ preferredDuringSchedulingIgnoredDuringExecution: (0, utils_1.undefinedIfEmpty)(this._podAntiAffinityPreferred),
1061
+ requiredDuringSchedulingIgnoredDuringExecution: (0, utils_1.undefinedIfEmpty)(this._podAntiAffinityRequired),
1062
+ } : undefined,
1063
+ } : undefined,
1064
+ nodeName: this._nodeName,
1065
+ tolerations: (0, utils_1.undefinedIfEmpty)(this._tolerations),
1066
+ };
1067
+ }
1068
+ }
1069
+ exports.PodScheduling = PodScheduling;
1070
+ /**
1071
+ * Isolation determines which policies are created
1072
+ * when allowing connections from a a pod / workload to peers.
1073
+ */
1074
+ var PodConnectionsIsolation;
1075
+ (function (PodConnectionsIsolation) {
1076
+ /**
1077
+ * Only creates network policies that select the pod.
1078
+ */
1079
+ PodConnectionsIsolation["POD"] = "POD";
1080
+ /**
1081
+ * Only creates network policies that select the peer.
1082
+ */
1083
+ PodConnectionsIsolation["PEER"] = "PEER";
1084
+ })(PodConnectionsIsolation || (exports.PodConnectionsIsolation = PodConnectionsIsolation = {}));
1085
+ /**
1086
+ * Controls network isolation rules for inter-pod communication.
1087
+ */
1088
+ class PodConnections {
1089
+ instance;
1090
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk8s-plus-36.PodConnections", version: "2.0.0" };
1091
+ constructor(instance) {
1092
+ this.instance = instance;
1093
+ }
1094
+ /**
1095
+ * Allow network traffic from this pod to the peer.
1096
+ *
1097
+ * By default, this will create an egress network policy for this pod, and an ingress
1098
+ * network policy for the peer. This is required if both sides are already isolated.
1099
+ * Use `options.isolation` to control this behavior.
1100
+ *
1101
+ * @example
1102
+ *
1103
+ * // create only an egress policy that selects the 'web' pod to allow outgoing traffic
1104
+ * // to the 'redis' pod. this requires the 'redis' pod to not be isolated for ingress.
1105
+ * web.connections.allowTo(redis, { isolation: Isolation.POD })
1106
+ *
1107
+ * // create only an ingress policy that selects the 'redis' peer to allow incoming traffic
1108
+ * // from the 'web' pod. this requires the 'web' pod to not be isolated for egress.
1109
+ * web.connections.allowTo(redis, { isolation: Isolation.PEER })
1110
+ *
1111
+ */
1112
+ allowTo(peer, options = {}) {
1113
+ return this.allow('Egress', peer, { ports: this.extractPorts(peer), ...options });
1114
+ }
1115
+ /**
1116
+ * Allow network traffic from the peer to this pod.
1117
+ *
1118
+ * By default, this will create an ingress network policy for this pod, and an egress
1119
+ * network policy for the peer. This is required if both sides are already isolated.
1120
+ * Use `options.isolation` to control this behavior.
1121
+ *
1122
+ * @example
1123
+ *
1124
+ * // create only an egress policy that selects the 'web' pod to allow outgoing traffic
1125
+ * // to the 'redis' pod. this requires the 'redis' pod to not be isolated for ingress.
1126
+ * redis.connections.allowFrom(web, { isolation: Isolation.PEER })
1127
+ *
1128
+ * // create only an ingress policy that selects the 'redis' peer to allow incoming traffic
1129
+ * // from the 'web' pod. this requires the 'web' pod to not be isolated for egress.
1130
+ * redis.connections.allowFrom(web, { isolation: Isolation.POD })
1131
+ *
1132
+ */
1133
+ allowFrom(peer, options = {}) {
1134
+ return this.allow('Ingress', peer, { ports: this.extractPorts(this.instance), ...options });
1135
+ }
1136
+ allow(direction, peer, options = {}) {
1137
+ const config = peer.toNetworkPolicyPeerConfig();
1138
+ networkpolicy.validatePeerConfig(config);
1139
+ const peerAddress = (0, utils_1.address)(peer);
1140
+ if (!options.isolation || options.isolation === PodConnectionsIsolation.POD) {
1141
+ const src = new networkpolicy.NetworkPolicy(this.instance, `Allow${direction}${peerAddress}`, {
1142
+ selector: this.instance,
1143
+ // the policy must be defined in the namespace of the pod
1144
+ // so it can select it.
1145
+ metadata: { namespace: this.instance.metadata.namespace },
1146
+ });
1147
+ switch (direction) {
1148
+ case 'Egress':
1149
+ src.addEgressRule(peer, options.ports);
1150
+ break;
1151
+ case 'Ingress':
1152
+ src.addIngressRule(peer, options.ports);
1153
+ }
1154
+ }
1155
+ if (!options.isolation || options.isolation === PodConnectionsIsolation.PEER) {
1156
+ if (config.ipBlock) {
1157
+ // for an ip block we don't need to create the opposite policies
1158
+ return;
1159
+ }
1160
+ const podSelector = peer.toPodSelector();
1161
+ if (!podSelector) {
1162
+ throw new Error(`Unable to create policies for peer '${peer.node.addr}' since its not a pod selector`);
1163
+ }
1164
+ const oppositeDirection = direction === 'Egress' ? 'Ingress' : 'Egress';
1165
+ const podSelectorConfig = podSelector.toPodSelectorConfig();
1166
+ let namespaces;
1167
+ if (!podSelectorConfig.namespaces) {
1168
+ // if the peer doesn't specify namespaces, we assume the same namespace.
1169
+ namespaces = [this.instance.metadata.namespace];
1170
+ }
1171
+ else {
1172
+ // a peer cannot specify namespaces by labels because
1173
+ // we won't be able to extract the names of those namespaces.
1174
+ if (podSelectorConfig.namespaces.labelSelector && !podSelectorConfig.namespaces.labelSelector.isEmpty()) {
1175
+ throw new Error(`Unable to create an ${oppositeDirection} policy for peer '${peer.node.path}' (pod=${this.instance.name}). Peer must specify namespaces only by name`);
1176
+ }
1177
+ // a peer must specify namespaces by name.
1178
+ if (!podSelectorConfig.namespaces.names) {
1179
+ throw new Error(`Unable to create an ${oppositeDirection} policy for peer '${peer.node.path}' (pod=${this.instance.name}). Peer must specify namespace names`);
1180
+ }
1181
+ namespaces = podSelectorConfig.namespaces.names;
1182
+ }
1183
+ for (const name of namespaces) {
1184
+ switch (direction) {
1185
+ case 'Egress':
1186
+ new networkpolicy.NetworkPolicy(this.instance, `AllowIngress${name}${peerAddress}`, {
1187
+ selector: podSelector,
1188
+ metadata: { namespace: name },
1189
+ ingress: { rules: [{ peer: this.instance, ports: options.ports }] },
1190
+ });
1191
+ break;
1192
+ case 'Ingress':
1193
+ new networkpolicy.NetworkPolicy(this.instance, `AllowEgress${name}${peerAddress}`, {
1194
+ selector: podSelector,
1195
+ metadata: { namespace: name },
1196
+ egress: { rules: [{ peer: this.instance, ports: options.ports }] },
1197
+ });
1198
+ break;
1199
+ default:
1200
+ throw new Error(`Unsupported direction: ${direction}`);
1201
+ }
1202
+ }
1203
+ }
1204
+ }
1205
+ extractPorts(selector) {
1206
+ return container.extractContainerPorts(selector).map(n => networkpolicy.NetworkPolicyPort.tcp(n.number));
1207
+ }
1208
+ /**
1209
+ * Sets the default network policy for Pod/Workload to have all egress and ingress connections as disabled
1210
+ */
1211
+ isolate() {
1212
+ new networkpolicy.NetworkPolicy(this.instance, 'DefaultDenyAll', {
1213
+ selector: this.instance,
1214
+ // the policy must be defined in the namespace of the pod
1215
+ // so it can select it.
1216
+ metadata: { namespace: this.instance.metadata.namespace },
1217
+ egress: {
1218
+ default: networkpolicy.NetworkPolicyTrafficDefault.DENY,
1219
+ },
1220
+ ingress: {
1221
+ default: networkpolicy.NetworkPolicyTrafficDefault.DENY,
1222
+ },
1223
+ });
1224
+ }
1225
+ }
1226
+ exports.PodConnections = PodConnections;
1227
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3BvZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaUNBQXNGO0FBQ3RGLDJDQUFtRDtBQUNuRCw2Q0FBK0I7QUFDL0IsdURBQXlDO0FBQ3pDLG1EQUFxQztBQUVyQyxnRUFBa0Q7QUFJbEQsbUNBQW9EO0FBR3BELE1BQXNCLFdBQVksU0FBUSxJQUFJLENBQUMsUUFBUTs7SUFFckMsYUFBYSxDQUFpQjtJQUM5QixjQUFjLENBQWtDO0lBQ2hELGVBQWUsQ0FBcUI7SUFDcEMsR0FBRyxDQUFTO0lBQ1osa0JBQWtCLENBQWtCO0lBQ3BDLDRCQUE0QixDQUFVO0lBQ3RDLHFCQUFxQixDQUFVO0lBQy9CLFdBQVcsQ0FBVztJQUN0QixzQkFBc0IsQ0FBWTtJQUNsQyxrQkFBa0IsQ0FBVztJQUUxQixPQUFPLENBQVU7SUFFbkIsV0FBVyxHQUEwQixFQUFFLENBQUM7SUFDeEMsZUFBZSxHQUEwQixFQUFFLENBQUM7SUFDNUMsWUFBWSxHQUFnQixFQUFFLENBQUM7SUFDL0IsUUFBUSxHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBSWxFLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsUUFBMEIsRUFBRTtRQUNwRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsSUFBSSxhQUFhLENBQUMsTUFBTSxDQUFDO1FBQ2pFLElBQUksQ0FBQyxjQUFjLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQztRQUMzQyxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksa0JBQWtCLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3JFLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FB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RUFBRTt5QkFDbkUsQ0FBQyxDQUFDO3dCQUNILE1BQU07b0JBQ1I7d0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsU0FBUyxFQUFFLENBQUMsQ0FBQztnQkFDM0QsQ0FBQztZQUNILENBQUM7UUFFSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLFlBQVksQ0FBQyxRQUEyQztRQUM5RCxPQUFPLFNBQVMsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzNHLENBQUM7SUFFRDs7T0FFRztJQUNJLE9BQU87UUFDWixJQUFJLGFBQWEsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRTtZQUMvRCxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7WUFDdkIseURBQXlEO1lBQ3pELHVCQUF1QjtZQUN2QixRQUFRLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFO1lBQ3pELE1BQU0sRUFBRTtnQkFDTixPQUFPLEVBQUUsYUFBYSxDQUFDLDJCQUEyQixDQUFDLElBQUk7YUFDeEQ7WUFDRCxPQUFPLEVBQUU7Z0JBQ1AsT0FBTyxFQUFFLGFBQWEsQ0FBQywyQkFBMkIsQ0FBQyxJQUFJO2FBQ3hEO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUE3Skgsd0NBOEpDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXBpT2JqZWN0LCBBcGlPYmplY3RNZXRhZGF0YURlZmluaXRpb24sIER1cmF0aW9uLCBMYXp5LCBOYW1lcyB9IGZyb20gJ2NkazhzJztcbmltcG9ydCB7IENvbnN0cnVjdCwgSUNvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0ICogYXMgYmFzZSBmcm9tICcuL2Jhc2UnO1xuaW1wb3J0ICogYXMgY29udGFpbmVyIGZyb20gJy4vY29udGFpbmVyJztcbmltcG9ydCAqIGFzIGs4cyBmcm9tICcuL2ltcG9ydHMvazhzJztcbmltcG9ydCAqIGFzIG5hbWVzcGFjZSBmcm9tICcuL25hbWVzcGFjZSc7XG5pbXBvcnQgKiBhcyBuZXR3b3JrcG9saWN5IGZyb20gJy4vbmV0d29yay1wb2xpY3knO1xuaW1wb3J0ICogYXMgcmIgZnJvbSAnLi9yb2xlLWJpbmRpbmcnO1xuaW1wb3J0ICogYXMgc2VjcmV0IGZyb20gJy4vc2VjcmV0JztcbmltcG9ydCAqIGFzIHNlcnZpY2VhY2NvdW50IGZyb20gJy4vc2VydmljZS1hY2NvdW50JztcbmltcG9ydCB7IHVuZGVmaW5lZElmRW1wdHksIGFkZHJlc3MgfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCAqIGFzIHZvbHVtZSBmcm9tICcuL3ZvbHVtZSc7XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBBYnN0cmFjdFBvZCBleHRlbmRzIGJhc2UuUmVzb3VyY2UgaW1wbGVtZW50cyBJUG9kU2VsZWN0b3IsIG5ldHdvcmtwb2xpY3kuSU5ldHdvcmtQb2xpY3lQZWVyLCByYi5JU3ViamVjdCB7XG5cbiAgcHVibGljIHJlYWRvbmx5IHJlc3RhcnRQb2xpY3k/OiBSZXN0YXJ0UG9saWN5O1xuICBwdWJsaWMgcmVhZG9ubHkgc2VydmljZUFjY291bnQ/OiBzZXJ2aWNlYWNjb3VudC5JU2VydmljZUFjY291bnQ7XG4gIHB1YmxpYyByZWFkb25seSBzZWN1cml0eUNvbnRleHQ6IFBvZFNlY3VyaXR5Q29udGV4dDtcbiAgcHVibGljIHJlYWRvbmx5IGRuczogUG9kRG5zO1xuICBwdWJsaWMgcmVhZG9ubHkgZG9ja2VyUmVnaXN0cnlBdXRoPzogc2VjcmV0LklTZWNyZXQ7XG4gIHB1YmxpYyByZWFkb25seSBhdXRvbW91bnRTZXJ2aWNlQWNjb3VudFRva2VuOiBib29sZWFuO1xuICBwdWJsaWMgcmVhZG9ubHkgc2hhcmVQcm9jZXNzTmFtZXNwYWNlOiBib29sZWFuO1xuICBwdWJsaWMgcmVhZG9ubHkgaG9zdE5ldHdvcms/OiBib29sZWFuO1xuICBwdWJsaWMgcmVhZG9ubHkgdGVybWluYXRpb25HcmFjZVBlcmlvZD86IER1cmF0aW9uO1xuICBwdWJsaWMgcmVhZG9ubHkgZW5hYmxlU2VydmljZUxpbmtzPzogYm9vbGVhbjtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNvbGF0ZTogYm9vbGVhbjtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9jb250YWluZXJzOiBjb250YWluZXIuQ29udGFpbmVyW10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBfaW5pdENvbnRhaW5lcnM6IGNvbnRhaW5lci5Db250YWluZXJbXSA9IFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IF9ob3N0QWxpYXNlczogSG9zdEFsaWFzW10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBfdm9sdW1lczogTWFwPHN0cmluZywgdm9sdW1lLlZvbHVtZT4gPSBuZXcgTWFwKCk7XG5cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHBvZE1ldGFkYXRhOiBBcGlPYmplY3RNZXRhZGF0YURlZmluaXRpb247XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEFic3RyYWN0UG9kUHJvcHMgPSB7fSkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLnJlc3RhcnRQb2xpY3kgPSBwcm9wcy5yZXN0YXJ0UG9saWN5ID8/IFJlc3RhcnRQb2xpY3kuQUxXQVlTO1xuICAgIHRoaXMuc2VydmljZUFjY291bnQgPSBwcm9wcy5zZXJ2aWNlQWNjb3VudDtcbiAgICB0aGlzLnNlY3VyaXR5Q29udGV4dCA9IG5ldyBQb2RTZWN1cml0eUNvbnRleHQocHJvcHMuc2VjdXJpdHlDb250ZXh0KTtcbiAgICB0aGlzLmRucyA9IG5ldyBQb2REbnMocHJvcHMuZG5zKTtcbiAgICB0aGlzLmRvY2tlclJlZ2lzdHJ5QXV0aCA9IHByb3BzLmRvY2tlclJlZ2lzdHJ5QXV0aDtcbiAgICB0aGlzLmF1dG9tb3VudFNlcnZpY2VBY2NvdW50VG9rZW4gPSBwcm9wcy5hdXRvbW91bnRTZXJ2aWNlQWNjb3VudFRva2VuID8/IGZhbHNlO1xuICAgIHRoaXMuc2hhcmVQcm9jZXNzTmFtZXNwYWNlID0gcHJvcHMuc2hhcmVQcm9jZXNzTmFtZXNwYWNlID8/IGZhbHNlO1xuICAgIHRoaXMuaXNvbGF0ZSA9IHByb3BzLmlzb2xhdGUgPz8gZmFsc2U7XG4gICAgdGhpcy5ob3N0TmV0d29yayA9IHByb3BzLmhvc3ROZXR3b3JrID8/IGZhbHNlO1xuICAgIHRoaXMudGVybWluYXRpb25HcmFjZVBlcmlvZCA9IHByb3BzLnRlcm1pbmF0aW9uR3JhY2VQZXJpb2QgPz8gRHVyYXRpb24uc2Vjb25kcygzMCk7XG4gICAgdGhpcy5lbmFibGVTZXJ2aWNlTGlua3MgPSBwcm9wcy5lbmFibGVTZXJ2aWNlTGlua3M7XG5cbiAgICBpZiAocHJvcHMuY29udGFpbmVycykge1xuICAgICAgcHJvcHMuY29udGFpbmVycy5mb3JFYWNoKGMgPT4gdGhpcy5hZGRDb250YWluZXIoYykpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy52b2x1bWVzKSB7XG4gICAgICBwcm9wcy52b2x1bWVzLmZvckVhY2godiA9PiB0aGlzLmFkZFZvbHVtZSh2KSk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmluaXRDb250YWluZXJzKSB7XG4gICAgICBwcm9wcy5pbml0Q29udGFpbmVycy5mb3JFYWNoKGMgPT4gdGhpcy5hZGRJbml0Q29udGFpbmVyKGMpKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuaG9zdEFsaWFzZXMpIHtcbiAgICAgIHByb3BzLmhvc3RBbGlhc2VzLmZvckVhY2goYyA9PiB0aGlzLmFkZEhvc3RBbGlhcyhjKSk7XG4gICAgfVxuXG4gIH1cblxuICBwdWJsaWMgZ2V0IGNvbnRhaW5lcnMoKTogY29udGFpbmVyLkNvbnRhaW5lcltdIHtcbiAgICByZXR1cm4gWy4uLnRoaXMuX2NvbnRhaW5lcnNdO1xuICB9XG5cbiAgcHVibGljIGdldCBpbml0Q29udGFpbmVycygpOiBjb250YWluZXIuQ29udGFpbmVyW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5faW5pdENvbnRhaW5lcnNdO1xuICB9XG5cbiAgcHVibGljIGdldCB2b2x1bWVzKCk6IHZvbHVtZS5Wb2x1bWVbXSB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5fdm9sdW1lcy52YWx1ZXMoKSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGhvc3RBbGlhc2VzKCk6IEhvc3RBbGlhc1tdIHtcbiAgICByZXR1cm4gWy4uLnRoaXMuX2hvc3RBbGlhc2VzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc2VlIElQb2RTZWxlY3Rvci50b1BvZFNlbGVjdG9yQ29uZmlnKClcbiAgICovXG4gIHB1YmxpYyB0b1BvZFNlbGVjdG9yQ29uZmlnKCk6IFBvZFNlbGVjdG9yQ29uZmlnIHtcbiAgICBjb25zdCBwb2RBZGRyZXNzID0gdGhpcy5wb2RNZXRhZGF0YS5nZXRMYWJlbChQb2QuQUREUkVTU19MQUJFTCk7XG4gICAgaWYgKCFwb2RBZGRyZXNzKSB7XG4gICAgICAvLyBzaG91bGRuJ3QgaGFwcGVuIGJlY2F1c2Ugd2UgYWRkIHRoaXMgbGFiZWwgYXV0b21hdGljYWxseSBpbiBib3RoIHBvZHMgYW5kIHdvcmtsb2Fkcy5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGNyZWF0ZSBhIGxhYmVsIHNlbGVjdG9yIHNpbmNlICR7UG9kLkFERFJFU1NfTEFCRUx9IGxhYmVsIGlzIG1pc3NpbmdgKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsU2VsZWN0b3I6IExhYmVsU2VsZWN0b3Iub2YoeyBsYWJlbHM6IHsgW1BvZC5BRERSRVNTX0xBQkVMXTogcG9kQWRkcmVzcyB9IH0pLFxuICAgICAgbmFtZXNwYWNlczogdGhpcy5tZXRhZGF0YS5uYW1lc3BhY2UgPyB7XG4gICAgICAgIG5hbWVzOiBbdGhpcy5tZXRhZGF0YS5uYW1lc3BhY2VdLFxuICAgICAgfSA6IHVuZGVmaW5lZCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEBzZWUgSU5ldHdvcmtQb2xpY3lQZWVyLnRvTmV0d29ya1BvbGljeVBlZXJDb25maWcoKVxuICAgKi9cbiAgcHVibGljIHRvTmV0d29ya1BvbGljeVBlZXJDb25maWcoKTogbmV0d29ya3BvbGljeS5OZXR3b3JrUG9saWN5UGVlckNvbmZpZyB7XG4gICAgcmV0dXJuIHsgcG9kU2VsZWN0b3I6IHRoaXMudG9Qb2RTZWxlY3RvckNvbmZpZygpIH07XG4gIH1cblxuICAvKipcbiAgICogQHNlZSBJTmV0d29ya1BvbGljeVBlZXIudG9Qb2RTZWxlY3RvcigpXG4gICAqL1xuICBwdWJsaWMgdG9Qb2RTZWxlY3RvcigpOiBJUG9kU2VsZWN0b3IgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIGFkZENvbnRhaW5lcihjb250OiBjb250YWluZXIuQ29udGFpbmVyUHJvcHMpOiBjb250YWluZXIuQ29udGFpbmVyIHtcbiAgICBjb25zdCBpbXBsID0gbmV3IGNvbnRhaW5lci5Db250YWluZXIoY29udCk7XG4gICAgdGhpcy5hdHRhY2hDb250YWluZXIoaW1wbCk7XG4gICAgcmV0dXJuIGltcGw7XG4gIH1cblxuICBwdWJsaWMgYXR0YWNoQ29udGFpbmVyKGNvbnQ6IGNvbnRhaW5lci5Db250YWluZXIpIHtcbiAgICB0aGlzLl9jb250YWluZXJzLnB1c2goY29udCk7XG4gIH1cblxuICBwdWJsaWMgYWRkSW5pdENvbnRhaW5lcihjb250OiBjb250YWluZXIuQ29udGFpbmVyUHJvcHMpOiBjb250YWluZXIuQ29udGFpbmVyIHtcblxuICAgIC8vIGh0dHBzOi8va3ViZXJuZXRlcy5pby9kb2NzL2NvbmNlcHRzL3dvcmtsb2Fkcy9wb2RzL2luaXQtY29udGFpbmVycy8jZGlmZmVyZW5jZXMtZnJvbS1yZWd1bGFyLWNvbnRhaW5lcnNcbiAgICBpZiAoIXRoaXMuaXNTaWRlY2FyQ29udGFpbmVyKGNvbnQpICYmIGNvbnQucmVhZGluZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0luaXQgY29udGFpbmVycyBtdXN0IG5vdCBoYXZlIGEgcmVhZGluZXNzIHByb2JlJyk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmlzU2lkZWNhckNvbnRhaW5lcihjb250KSAmJiBjb250LmxpdmVuZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0luaXQgY29udGFpbmVycyBtdXN0IG5vdCBoYXZlIGEgbGl2ZW5lc3MgcHJvYmUnKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNTaWRlY2FyQ29udGFpbmVyKGNvbnQpICYmIGNvbnQuc3RhcnR1cCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbml0IGNvbnRhaW5lcnMgbXVzdCBub3QgaGF2ZSBhIHN0YXJ0dXAgcHJvYmUnKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbXBsID0gbmV3IGNvbnRhaW5lci5Db250YWluZXIoe1xuICAgICAgLi4uY29udCxcbiAgICAgIG5hbWU6IGNvbnQubmFtZSA/PyBgaW5pdC0ke3RoaXMuX2luaXRDb250YWluZXJzLmxlbmd0aH1gLFxuICAgIH0pO1xuXG4gICAgdGhpcy5faW5pdENvbnRhaW5lcnMucHVzaChpbXBsKTtcbiAgICByZXR1cm4gaW1wbDtcbiAgfVxuXG4gIC8vIEFueSBpbml0Q29udGFpbmVyIHRoYXQgaGFzIGByZXN0YXJ0UG9saWN5PUFsd2F5c2AgaXMgYSBzaWRlY2FyIGNvbnRhaW5lci4gUGxlYXNlIHJlZmVyIHRvXG4gIC8vIGRvY3VtZW50YXRpb24gZm9yIG1vcmUgZGV0YWlsczpcbiAgLy8gaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvd29ya2xvYWRzL3BvZHMvc2lkZWNhci1jb250YWluZXJzLyNkaWZmZXJlbmNlcy1mcm9tLWluaXQtY29udGFpbmVyc1xuICBwcml2YXRlIGlzU2lkZWNhckNvbnRhaW5lcihjb250OiBjb250YWluZXIuQ29udGFpbmVyUHJvcHMpIHtcbiAgICByZXR1cm4gY29udC5yZXN0YXJ0UG9saWN5ID09PSBjb250YWluZXIuQ29udGFpbmVyUmVzdGFydFBvbGljeS5BTFdBWVM7XG4gIH1cblxuICBwdWJsaWMgYWRkSG9zdEFsaWFzKGhvc3RBbGlhczogSG9zdEFsaWFzKTogdm9pZCB7XG4gICAgdGhpcy5faG9zdEFsaWFzZXMucHVzaChob3N0QWxpYXMpO1xuICB9XG5cbiAgcHVibGljIGFkZFZvbHVtZSh2b2w6IHZvbHVtZS5Wb2x1bWUpOiB2b2lkIHtcbiAgICBjb25zdCBleGlzdGluZ1ZvbHVtZSA9IHRoaXMuX3ZvbHVtZXMuZ2V0KHZvbC5uYW1lKTtcbiAgICBpZiAoZXhpc3RpbmdWb2x1bWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVm9sdW1lIHdpdGggbmFtZSAke3ZvbC5uYW1lfSBhbHJlYWR5IGV4aXN0c2ApO1xuICAgIH1cbiAgICB0aGlzLl92b2x1bWVzLnNldCh2b2wubmFtZSwgdm9sKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc2VlIElTdWJlY3QudG9TdWJqZWN0Q29uZmlndXJhdGlvbigpXG4gICAqL1xuICBwdWJsaWMgdG9TdWJqZWN0Q29uZmlndXJhdGlvbigpOiByYi5TdWJqZWN0Q29uZmlndXJhdGlvbiB7XG5cbiAgICBpZiAoIXRoaXMuc2VydmljZUFjY291bnQgJiYgIXRoaXMuYXV0b21vdW50U2VydmljZUFjY291bnRUb2tlbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMubmFtZX0gY2Fubm90IGJlIGNvbnZlcnRlZCB0byBhIHJvbGUgYmluZGluZyBzdWJqZWN0OmBcbiAgICAgICAgKyAnIFlvdSBtdXN0IGVpdGhlciBhc3NpZ24gYSBzZXJ2aWNlIGFjY291bnQgdG8gaXQsIG9yIHVzZSBcXCdhdXRvbW91bnRTZXJ2aWNlQWNjb3VudFRva2VuOiB0cnVlXFwnJyk7XG4gICAgfVxuXG4gICAgLy8gJ2RlZmF1bHQnIGlzIGFzc3VtZWQgdG8gYmUgdGhlIG5hbWUgb2YgdGhlIGRlZmF1bHQgc2VydmljZSBhY2NvdW50XG4gICAgLy8gaW4gdGhlIGNsdXN0ZXIuXG4gICAgY29uc3Qgc2VydmljZUFjY291bnROYW1lID0gdGhpcy5zZXJ2aWNlQWNjb3VudD8ubmFtZSA/PyAnZGVmYXVsdCc7XG5cbiAgICByZXR1cm4ge1xuICAgICAga2luZDogJ1NlcnZpY2VBY2NvdW50JyxcbiAgICAgIG5hbWU6IHNlcnZpY2VBY2NvdW50TmFtZSxcbiAgICAgIGFwaUdyb3VwOiAnJyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF90b1BvZFNwZWMoKTogazhzLlBvZFNwZWMge1xuXG4gICAgaWYgKHRoaXMuY29udGFpbmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUG9kU3BlYyBtdXN0IGhhdmUgYXQgbGVhc3QgMSBjb250YWluZXInKTtcbiAgICB9XG5cbiAgICBjb25zdCB2b2x1bWVzOiBNYXA8c3RyaW5nLCB2b2x1bWUuVm9sdW1lPiA9IG5ldyBNYXAoKTtcbiAgICBjb25zdCBjb250YWluZXJzOiBrOHMuQ29udGFpbmVyW10gPSBbXTtcbiAgICBjb25zdCBpbml0Q29udGFpbmVyczogazhzLkNvbnRhaW5lcltdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGNvbnQgb2YgdGhpcy5jb250YWluZXJzKSB7XG4gICAgICAvLyBjaGVjayBpZiByZXN0YXJ0UG9saWN5IGlzIGRlZmluZWQgZm9yIGNvbnRhaW5lcnNcbiAgICAgIGlmIChjb250LnJlc3RhcnRQb2xpY3kpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGNvbnRhaW5lciBzcGVjOiAke2NvbnQubmFtZX0gaGFzIG5vbi1lbXB0eSByZXN0YXJ0UG9saWN5IGZpZWxkLiBUaGUgZmllbGQgY2FuIG9ubHkgYmUgc3BlY2lmaWVkIGZvciBpbml0Q29udGFpbmVyc2ApO1xuICAgICAgfVxuICAgICAgLy8gYXV0b21hdGljYWxseSBhZGQgdm9sdW1lIGZyb20gdGhlIGNvbnRhaW5lciBtb3VudFxuICAgICAgLy8gdG8gdGhpcyBwb2Qgc28gdGhhdHMgaXRzIGF2YWlsYWJsZSB0byB0aGUgY29udGFpbmVyLlxuICAgICAgZm9yIChjb25zdCBtb3VudCBvZiBjb250Lm1vdW50cykge1xuICAgICAgICBhZGRWb2x1bWUobW91bnQudm9sdW1lKTtcbiAgICAgIH1cbiAgICAgIGNvbnRhaW5lcnMucHVzaChjb250Ll90b0t1YmUoKSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBjb250IG9mIHRoaXMuaW5pdENvbnRhaW5lcnMpIHtcbiAgICAgIC8vIGF1dG9tYXRpY2FsbHkgYWRkIHZvbHVtZSBmcm9tIHRoZSBjb250YWluZXIgbW91bnRcbiAgICAgIC8vIHRvIHRoaXMgcG9kIHNvIHRoYXRzIGl0cyBhdmFpbGFibGUgdG8gdGhlIGNvbnRhaW5lci5cbiAgICAgIGZvciAoY29uc3QgbW91bnQgb2YgY29udC5tb3VudHMpIHtcbiAgICAgICAgYWRkVm9sdW1lKG1vdW50LnZvbHVtZSk7XG4gICAgICB9XG4gICAgICBpbml0Q29udGFpbmVycy5wdXNoKGNvbnQuX3RvS3ViZSgpKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHZvbCBvZiB0aGlzLnZvbHVtZXMpIHtcbiAgICAgIGFkZFZvbHVtZSh2b2wpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFZvbHVtZSh2b2w6IHZvbHVtZS5Wb2x1bWUpIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nVm9sdW1lID0gdm9sdW1lcy5nZXQodm9sLm5hbWUpO1xuICAgICAgLy8gaXRzIG9rIHRvIGNhbGwgdGhpcyBmdW5jdGlvbiB0d2ljZSBvbiB0aGUgc2FtZSB2b2x1bWUsIGJ1dCBpdHMgbm90IG9rIHRvXG4gICAgICAvLyBjYWxsIGl0IHR3aWNlIG9uIGEgZGlmZmVyZW50IHZvbHVtZSB3aXRoIHRoZSBzYW1lIG5hbWUuXG4gICAgICBpZiAoZXhpc3RpbmdWb2x1bWUgJiYgZXhpc3RpbmdWb2x1bWUgIT09IHZvbCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbW91bnQgY29uZmlndXJhdGlvbi4gQXQgbGVhc3QgdHdvIGRpZmZlcmVudCB2b2x1bWVzIGhhdmUgdGhlIHNhbWUgbmFtZTogJHt2b2wubmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIHZvbHVtZXMuc2V0KHZvbC5uYW1lLCB2b2wpO1xuICAgIH1cblxuICAgIGNvbnN0IGRucyA9IHRoaXMuZG5zLl90b0t1YmUoKTtcblxuICAgIHJldHVybiB7XG4gICAgICByZXN0YXJ0UG9saWN5OiB0aGlzLnJlc3RhcnRQb2xpY3ksXG4gICAgICBzZXJ2aWNlQWNjb3VudE5hbWU6IHRoaXMuc2VydmljZUFjY291bnQ/Lm5hbWUsXG4gICAgICBjb250YWluZXJzOiBjb250YWluZXJzLFxuICAgICAgc2VjdXJpdHlDb250ZXh0OiB1bmRlZmluZWRJZkVtcHR5KHRoaXMuc2VjdXJpdHlDb250ZXh0Ll90b0t1YmUoKSksXG4gICAgICBpbml0Q29udGFpbmVyczogdW5kZWZpbmVkSWZFbXB0eShpbml0Q29udGFpbmVycyksXG4gICAgICBob3N0QWxpYXNlczogdW5kZWZpbmVkSWZFbXB0eSh0aGlzLmhvc3RBbGlhc2VzKSxcbiAgICAgIHZvbHVtZXM6IHVuZGVmaW5lZElmRW1wdHkoQXJyYXkuZnJvbSh2b2x1bWVzLnZhbHVlcygpKS5tYXAodiA9PiB2Ll90b0t1YmUoKSkpLFxuICAgICAgZG5zUG9saWN5OiBkbnMucG9saWN5LFxuICAgICAgZG5zQ29uZmlnOiB1bmRlZmluZWRJZkVtcHR5KGRucy5jb25maWcpLFxuICAgICAgaG9zdG5hbWU6IGRucy5ob3N0bmFtZSxcbiAgICAgIHN1YmRvbWFpbjogZG5zLnN1YmRvbWFpbixcbiAgICAgIHNldEhvc3RuYW1lQXNGcWRuOiBkbnMuaG9zdG5hbWVBc0ZRRE4sXG4gICAgICBpbWFnZVB1bGxTZWNyZXRzOiB0aGlzLmRvY2tlclJlZ2lzdHJ5QXV0aCA/IFt7IG5hbWU6IHRoaXMuZG9ja2VyUmVnaXN0cnlBdXRoLm5hbWUgfV0gOiB1bmRlZmluZWQsXG4gICAgICBhdXRvbW91bnRTZXJ2aWNlQWNjb3VudFRva2VuOiB0aGlzLmF1dG9tb3VudFNlcnZpY2VBY2NvdW50VG9rZW4sXG4gICAgICBzaGFyZVByb2Nlc3NOYW1lc3BhY2U6IHRoaXMuc2hhcmVQcm9jZXNzTmFtZXNwYWNlLFxuICAgICAgaG9zdE5ldHdvcms6IHRoaXMuaG9zdE5ldHdvcmssXG4gICAgICB0ZXJtaW5hdGlvbkdyYWNlUGVyaW9kU2Vjb25kczogdGhpcy50ZXJtaW5hdGlvbkdyYWNlUGVyaW9kPy50b1NlY29uZHMoKSxcbiAgICAgIGVuYWJsZVNlcnZpY2VMaW5rczogdGhpcy5lbmFibGVTZXJ2aWNlTGlua3MsXG4gICAgfTtcblxuICB9XG5cbn1cblxuLyoqXG4gKiBTeXNjdGwgZGVmaW5lcyBhIGtlcm5lbCBwYXJhbWV0ZXIgdG8gYmUgc2V0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3lzY3RsIHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgYSBwcm9wZXJ0eSB0byBzZXRcbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVmFsdWUgb2YgYSBwcm9wZXJ0eSB0byBzZXRcbiAgICovXG4gIHJlYWRvbmx5IHZhbHVlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYFBvZFNlY3VyaXR5Q29udGV4dGBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQb2RTZWN1cml0eUNvbnRleHRQcm9wcyB7XG5cbiAgLyoqXG4gICAqIE1vZGlmeSB0aGUgb3duZXJzaGlwIGFuZCBwZXJtaXNzaW9ucyBvZiBwb2Qgdm9sdW1lcyB0byB0aGlzIEdJRC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBWb2x1bWUgb3duZXJzaGlwIGlzIG5vdCBjaGFuZ2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgZnNHcm91cD86IG51bWJlcjtcblxuICAvKipcbiAgICogRGVmaW5lcyBiZWhhdmlvciBvZiBjaGFuZ2luZyBvd25lcnNoaXAgYW5kIHBlcm1pc3Npb24gb2YgdGhlIHZvbHVtZSBiZWZvcmUgYmVpbmcgZXhwb3NlZCBpbnNpZGUgUG9kLlxuICAgKiBUaGlzIGZpZWxkIHdpbGwgb25seSBhcHBseSB0byB2b2x1bWUgdHlwZXMgd2hpY2ggc3VwcG9ydCBmc0dyb3VwIGJhc2VkIG93bmVyc2hpcChhbmQgcGVybWlzc2lvbnMpLlxuICAgKiBJdCB3aWxsIGhhdmUgbm8gZWZmZWN0IG9uIGVwaGVtZXJhbCB2b2x1bWUgdHlwZXMgc3VjaCBhczogc2VjcmV0LCBjb25maWdtYXBzIGFuZCBlbXB0eWRpci5cbiAgICpcbiAgICogQGRlZmF1bHQgRnNHcm91cENoYW5nZVBvbGljeS5BTFdBWVNcbiAgICovXG4gIHJlYWRvbmx5IGZzR3JvdXBDaGFuZ2VQb2xpY3k/OiBGc0dyb3VwQ2hhbmdlUG9saWN5O1xuXG4gIC8qKlxuICAgKiBUaGUgVUlEIHRvIHJ1biB0aGUgZW50cnlwb2ludCBvZiB0aGUgY29udGFpbmVyIHByb2Nlc3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVXNlciBzcGVjaWZpZWQgaW4gaW1hZ2UgbWV0YWRhdGFcbiAgICovXG4gIHJlYWRvbmx5IHVzZXI/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBHSUQgdG8gcnVuIHRoZSBlbnRyeXBvaW50IG9mIHRoZSBjb250YWluZXIgcHJvY2Vzcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBHcm91cCBjb25maWd1cmVkIGJ5IGNvbnRhaW5lciBydW50aW1lXG4gICAqL1xuICByZWFkb25seSBncm91cD86IG51bWJlcjtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHRoYXQgdGhlIGNvbnRhaW5lciBtdXN0IHJ1biBhcyBhIG5vbi1yb290IHVzZXIuXG4gICAqIElmIHRydWUsIHRoZSBLdWJlbGV0IHdpbGwgdmFsaWRhdGUgdGhlIGltYWdlIGF0IHJ1bnRpbWUgdG8gZW5zdXJlIHRoYXQgaXQgZG9lc1xuICAgKiBub3QgcnVuIGFzIFVJRCAwIChyb290KSBhbmQgZmFpbCB0byBzdGFydCB0aGUgY29udGFpbmVyIGlmIGl0IGRvZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGVuc3VyZU5vblJvb3Q/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTeXNjdGxzIGhvbGQgYSBsaXN0IG9mIG5hbWVzcGFjZWQgc3lzY3RscyB1c2VkIGZvciB0aGUgcG9kLlxuICAgKiBQb2RzIHdpdGggdW5zdXBwb3J0ZWQgc3lzY3RscyAoYnkgdGhlIGNvbnRhaW5lciBydW50aW1lKSBtaWdodCBmYWlsIHRvIGxhdW5jaC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBzeXNjdGxzXG4gICAqL1xuICByZWFkb25seSBzeXNjdGxzPzogU3lzY3RsW107XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYEFic3RyYWN0UG9kYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBYnN0cmFjdFBvZFByb3BzIGV4dGVuZHMgYmFzZS5SZXNvdXJjZVByb3BzIHtcblxuICAvKipcbiAgICogTGlzdCBvZiBjb250YWluZXJzIGJlbG9uZ2luZyB0byB0aGUgcG9kLiBDb250YWluZXJzIGNhbm5vdCBjdXJyZW50bHkgYmVcbiAgICogYWRkZWQgb3IgcmVtb3ZlZC4gVGhlcmUgbXVzdCBiZSBhdCBsZWFzdCBvbmUgY29udGFpbmVyIGluIGEgUG9kLlxuICAgKlxuICAgKiBZb3UgY2FuIGFkZCBhZGRpdGlvbm5hbCBjb250YWluZXJzIHVzaW5nIGBwb2RTcGVjLmFkZENvbnRhaW5lcigpYFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGNvbnRhaW5lcnMuIE5vdGUgdGhhdCBhIHBvZCBzcGVjIG11c3QgaW5jbHVkZSBhdCBsZWFzdCBvbmUgY29udGFpbmVyLlxuICAgKi9cbiAgcmVhZG9ubHkgY29udGFpbmVycz86IGNvbnRhaW5lci5Db250YWluZXJQcm9wc1tdO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIGluaXRpYWxpemF0aW9uIGNvbnRhaW5lcnMgYmVsb25naW5nIHRvIHRoZSBwb2QuXG4gICAqIEluaXQgY29udGFpbmVycyBhcmUgZXhlY3V0ZWQgaW4gb3JkZXIgcHJpb3IgdG8gY29udGFpbmVycyBiZWluZyBzdGFydGVkLlxuICAgKiBJZiBhbnkgaW5pdCBjb250YWluZXIgZmFpbHMsIHRoZSBwb2QgaXMgY29uc2lkZXJlZCB0byBoYXZlIGZhaWxlZCBhbmQgaXMgaGFuZGxlZCBhY2NvcmRpbmcgdG8gaXRzIHJlc3RhcnRQb2xpY3kuXG4gICAqIFRoZSBuYW1lIGZvciBhbiBpbml0IGNvbnRhaW5lciBvciBub3JtYWwgY29udGFpbmVyIG11c3QgYmUgdW5pcXVlIGFtb25nIGFsbCBjb250YWluZXJzLlxuICAgKiBJbml0IGNvbnRhaW5lcnMgbWF5IG5vdCBoYXZlIExpZmVjeWNsZSBhY3Rpb25zLCBSZWFkaW5lc3MgcHJvYmVzLCBMaXZlbmVzcyBwcm9iZXMsIG9yIFN0YXJ0dXAgcHJvYmVzLlxuICAgKiBUaGUgcmVzb3VyY2VSZXF1aXJlbWVudHMgb2YgYW4gaW5pdCBjb250YWluZXIgYXJlIHRha2VuIGludG8gYWNjb3VudCBkdXJpbmcgc2NoZWR1bGluZyBieSBmaW5kaW5nIHRoZSBoaWdoZXN0IHJlcXVlc3QvbGltaXRcbiAgICogZm9yIGVhY2ggcmVzb3VyY2UgdHlwZSwgYW5kIHRoZW4gdXNpbmcgdGhlIG1heCBvZiBvZiB0aGF0IHZhbHVlIG9yIHRoZSBzdW0gb2YgdGhlIG5vcm1hbCBjb250YWluZXJzLlxuICAgKiBMaW1pdHMgYXJlIGFwcGxpZWQgdG8gaW5pdCBjb250YWluZXJzIGluIGEgc2ltaWxhciBmYXNoaW9uLlxuICAgKlxuICAgKiBJbml0IGNvbnRhaW5lcnMgY2Fubm90IGN1cnJlbnRseSBiZSBhZGRlZCAscmVtb3ZlZCBvciB1cGRhdGVkLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8va3ViZXJuZXRlcy5pby9kb2NzL2NvbmNlcHRzL3dvcmtsb2Fkcy9wb2RzL2luaXQtY29udGFpbmVycy9cbiAgICogQGRlZmF1bHQgLSBObyBpbml0IGNvbnRhaW5lcnMuXG4gICAqL1xuICByZWFkb25seSBpbml0Q29udGFpbmVycz86IGNvbnRhaW5lci5Db250YWluZXJQcm9wc1tdO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIHZvbHVtZXMgdGhhdCBjYW4gYmUgbW91bnRlZCBieSBjb250YWluZXJzIGJlbG9uZ2luZyB0byB0aGUgcG9kLlxuICAgKlxuICAgKiBZb3UgY2FuIGFsc28gYWRkIHZvbHVtZXMgbGF0ZXIgdXNpbmcgYHBvZFNwZWMuYWRkVm9sdW1lKClgXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvc3RvcmFnZS92b2x1bWVzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gdm9sdW1lcy5cbiAgICovXG4gIHJlYWRvbmx5IHZvbHVtZXM/OiB2b2x1bWUuVm9sdW1lW107XG5cbiAgLyoqXG4gICAqIFJlc3RhcnQgcG9saWN5IGZvciBhbGwgY29udGFpbmVycyB3aXRoaW4gdGhlIHBvZC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2t1YmVybmV0ZXMuaW8vZG9jcy9jb25jZXB0cy93b3JrbG9hZHMvcG9kcy9wb2QtbGlmZWN5Y2xlLyNyZXN0YXJ0LXBvbGljeVxuICAgKlxuICAgKiBAZGVmYXVsdCBSZXN0YXJ0UG9saWN5LkFMV0FZU1xuICAgKi9cbiAgcmVhZG9ubHkgcmVzdGFydFBvbGljeT86IFJlc3RhcnRQb2xpY3k7XG5cbiAgLyoqXG4gICAqIEEgc2VydmljZSBhY2NvdW50IHByb3ZpZGVzIGFuIGlkZW50aXR5IGZvciBwcm9jZXNzZXMgdGhhdCBydW4gaW4gYSBQb2QuXG4gICAqXG4gICAqIFdoZW4geW91IChhIGh1bWFuKSBhY2Nlc3MgdGhlIGNsdXN0ZXIgKGZvciBleGFtcGxlLCB1c2luZyBrdWJlY3RsKSwgeW91IGFyZVxuICAgKiBhdXRoZW50aWNhdGVkIGJ5IHRoZSBhcGlzZXJ2ZXIgYXMgYSBwYXJ0aWN1bGFyIFVzZXIgQWNjb3VudCAoY3VycmVudGx5IHRoaXNcbiAgICogaXMgdXN1YWxseSBhZG1pbiwgdW5sZXNzIHlvdXIgY2x1c3RlciBhZG1pbmlzdHJhdG9yIGhhcyBjdXN0b21pemVkIHlvdXJcbiAgICogY2x1c3RlcikuIFByb2Nlc3NlcyBpbiBjb250YWluZXJzIGluc2lkZSBwb2RzIGNhbiBhbHNvIGNvbnRhY3QgdGhlXG4gICAqIGFwaXNlcnZlci4gV2hlbiB0aGV5IGRvLCB0aGV5IGFyZSBhdXRoZW50aWNhdGVkIGFzIGEgcGFydGljdWxhciBTZXJ2aWNlXG4gICAqIEFjY291bnQgKGZvciBleGFtcGxlLCBkZWZhdWx0KS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2t1YmVybmV0ZXMuaW8vZG9jcy90YXNrcy9jb25maWd1cmUtcG9kLWNvbnRhaW5lci9jb25maWd1cmUtc2VydmljZS1hY2NvdW50L1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHNlcnZpY2UgYWNjb3VudC5cbiAgICovXG4gIHJlYWRvbmx5IHNlcnZpY2VBY2NvdW50Pzogc2VydmljZWFjY291bnQuSVNlcnZpY2VBY2NvdW50O1xuXG4gIC8qKlxuICAgKiBTZWN1cml0eUNvbnRleHQgaG9sZHMgcG9kLWxldmVsIHNlY3VyaXR5IGF0dHJpYnV0ZXMgYW5kIGNvbW1vbiBjb250YWluZXIgc2V0dGluZ3MuXG4gICAqXG4gICAqIEBkZWZhdWx0XG4gICAqXG4gICAqICAgZnNHcm91cENoYW5nZVBvbGljeTogRnNHcm91cENoYW5nZVBvbGljeS5Gc0dyb3VwQ2hhbmdlUG9saWN5LkFMV0FZU1xuICAgKiAgIGVuc3VyZU5vblJvb3Q6IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHNlY3VyaXR5Q29udGV4dD86IFBvZFNlY3VyaXR5Q29udGV4dFByb3BzO1xuXG4gIC8qKlxuICAgKiBIb3N0QWxpYXMgaG9sZHMgdGhlIG1hcHBpbmcgYmV0d2VlbiBJUCBhbmQgaG9zdG5hbWVzIHRoYXQgd2lsbCBiZSBpbmplY3RlZCBhcyBhbiBlbnRyeSBpbiB0aGUgcG9kJ3MgaG9zdHMgZmlsZS5cbiAgICpcbiAgICogQHNjaGVtYSBpby5rOHMuYXBpLmNvcmUudjEuSG9zdEFsaWFzXG4gICAqL1xuICByZWFkb25seSBob3N0QWxpYXNlcz86IEhvc3RBbGlhc1tdO1xuXG4gIC8qKlxuICAgKiBETlMgc2V0dGluZ3MgZm9yIHRoZSBwb2QuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvc2VydmljZXMtbmV0d29ya2luZy9kbnMtcG9kLXNlcnZpY2UvXG4gICAqXG4gICAqIEBkZWZhdWx0XG4gICAqXG4gICAqICBwb2xpY3k6IERuc1BvbGljeS5DTFVTVEVSX0ZJUlNUXG4gICAqICBob3N0bmFtZUFzRlFETjogZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGRucz86IFBvZERuc1Byb3BzO1xuXG4gIC8qKlxuICAgKiBBIHNlY3JldCBjb250YWluaW5nIGRvY2tlciBjcmVkZW50aWFscyBmb3IgYXV0aGVudGljYXRpbmcgdG8gYSByZWdpc3RyeS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBhdXRoLiBJbWFnZXMgYXJlIGFzc3VtZWQgdG8gYmUgcHVibGljbHkgYXZhaWxhYmxlLlxuICAgKi9cbiAgcmVhZG9ubHkgZG9ja2VyUmVnaXN0cnlBdXRoPzogc2VjcmV0LklTZWNyZXQ7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIGEgc2VydmljZSBhY2NvdW50IHRva2VuIHNob3VsZCBiZSBhdXRvbWF0aWNhbGx5IG1vdW50ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvdGFza3MvY29uZmlndXJlLXBvZC1jb250YWluZXIvY29uZmlndXJlLXNlcnZpY2UtYWNjb3VudC8jdXNlLXRoZS1kZWZhdWx0LXNlcnZpY2UtYWNjb3VudC10by1hY2Nlc3MtdGhlLWFwaS1zZXJ2ZXJcbiAgICovXG4gIHJlYWRvbmx5IGF1dG9tb3VudFNlcnZpY2VBY2NvdW50VG9rZW4/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGVuIHByb2Nlc3MgbmFtZXNwYWNlIHNoYXJpbmcgaXMgZW5hYmxlZCwgcHJvY2Vzc2VzIGluIGEgY29udGFpbmVyIGFyZSB2aXNpYmxlIHRvIGFsbCBvdGhlciBjb250YWluZXJzIGluIHRoZSBzYW1lIHBvZC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQHNlZSBodHRwczovL2t1YmVybmV0ZXMuaW8vZG9jcy90YXNrcy9jb25maWd1cmUtcG9kLWNvbnRhaW5lci9zaGFyZS1wcm9jZXNzLW5hbWVzcGFjZS9cbiAgICovXG4gIHJlYWRvbmx5IHNoYXJlUHJvY2Vzc05hbWVzcGFjZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIElzb2xhdGVzIHRoZSBwb2QuIFRoaXMgd2lsbCBwcmV2ZW50IGFueSBpbmdyZXNzIG9yIGVncmVzcyBjb25uZWN0aW9ucyB0byAvIGZyb20gdGhpcyBwb2QuXG4gICAqIFlvdSBjYW4gaG93ZXZlciBhbGxvdyBleHBsaWNpdCBjb25uZWN0aW9ucyBwb3N0IGluc3RhbnRpYXRpb24gYnkgdXNpbmcgdGhlIGAuY29ubmVjdGlvbnNgIHByb3BlcnR5LlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgaXNvbGF0ZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEhvc3QgbmV0d29yayBmb3IgdGhlIHBvZC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGhvc3ROZXR3b3JrPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogR3JhY2UgcGVyaW9kIHVudGlsIHRoZSBwb2QgaXMgdGVybWluYXRlZFxuICAgKlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5zZWNvbmRzKDMwKVxuICAgKi9cbiAgcmVhZG9ubHkgdGVybWluYXRpb25HcmFjZVBlcmlvZD86IER1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciBpbmZvcm1hdGlvbiBhYm91dCBzZXJ2aWNlcyBzaG91bGQgYmUgaW5qZWN0ZWQgaW50byBwb2Qnc1xuICAgKiBlbnZpcm9ubWVudCB2YXJpYWJsZXMsIG1hdGNoaW5nIHRoZSBzeW50YXggb2YgRG9ja2VyIGxpbmtzLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvc2VydmljZXMtbmV0d29ya2luZy9jb25uZWN0LWFwcGxpY2F0aW9ucy1zZXJ2aWNlLyNhY2Nlc3NpbmctdGhlLXNlcnZpY2VcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZVNlcnZpY2VMaW5rcz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYFBvZGAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9kUHJvcHMgZXh0ZW5kcyBBYnN0cmFjdFBvZFByb3BzIHtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgTGFiZWxTZWxlY3Rvci5vZmAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGFiZWxTZWxlY3Rvck9wdGlvbnMge1xuXG4gIC8qKlxuICAgKiBTdHJpY3QgbGFiZWwgbWF0Y2hlcnMuXG4gICAqL1xuICByZWFkb25seSBsYWJlbHM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBFeHByZXNzaW9uIGJhc2VkIGxhYmVsIG1hdGNoZXJzLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhwcmVzc2lvbnM/OiBMYWJlbEV4cHJlc3Npb25bXTtcbn1cblxuLyoqXG4gKiBNYXRjaCBhIHJlc291cmNlIGJ5IGxhYmVscy5cbiAqL1xuZXhwb3J0IGNsYXNzIExhYmVsU2VsZWN0b3Ige1xuXG4gIHB1YmxpYyBzdGF0aWMgb2Yob3B0aW9uczogTGFiZWxTZWxlY3Rvck9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBuZXcgTGFiZWxTZWxlY3RvcihvcHRpb25zLmV4cHJlc3Npb25zID8/IFtdLCBvcHRpb25zLmxhYmVscyA/PyB7fSk7XG4gIH1cblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZXhwcmVzc2lvbnM6IExhYmVsRXhwcmVzc2lvbltdLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbGFiZWxzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KSB7XG4gIH1cblxuICBwdWJsaWMgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5leHByZXNzaW9ucy5sZW5ndGggPT09IDAgJiYgT2JqZWN0LmtleXModGhpcy5sYWJlbHMpLmxlbmd0aCA9PT0gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBfdG9LdWJlKCk6IGs4cy5MYWJlbFNlbGVjdG9yIHtcbiAgICBpZiAodGhpcy5pc0VtcHR5KCkpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIG1hdGNoRXhwcmVzc2lvbnM6IHVuZGVmaW5lZElmRW1wdHkodGhpcy5leHByZXNzaW9ucy5tYXAocSA9PiAoe1xuICAgICAgICBrZXk6IHEua2V5LFxuICAgICAgICBvcGVyYXRvcjogcS5vcGVyYXRvcixcbiAgICAgICAgdmFsdWVzOiBxLnZhbHVlcyxcbiAgICAgIH0pKSksXG4gICAgICBtYXRjaExhYmVsczogdW5kZWZpbmVkSWZFbXB0eSh0aGlzLmxhYmVscyksXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHNlbGVjdGluZyBwb2RzLCBvcHRpb25hbGx5IGluIHBhcnRpY3VsYXIgbmFtZXNwYWNlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQb2RTZWxlY3RvckNvbmZpZyB7XG5cbiAgLyoqXG4gICAqIEEgc2VsZWN0b3IgdG8gc2VsZWN0IHBvZHMgYnkgbGFiZWxzLlxuICAgKi9cbiAgcmVhZG9ubHkgbGFiZWxTZWxlY3RvcjogTGFiZWxTZWxlY3RvcjtcblxuICAvKipcbiAgICogQ29uZmlndXJhdGlvbiBmb3Igc2VsZWN0aW5nIHdoaWNoIG5hbWVwc2FjZXMgYXJlIHRoZSBwb2RzIGFsbG93ZWQgdG8gYmUgaW4uXG4gICAqL1xuICByZWFkb25seSBuYW1lc3BhY2VzPzogbmFtZXNwYWNlLk5hbWVzcGFjZVNlbGVjdG9yQ29uZmlnO1xuXG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBvYmplY3QgdGhhdCBjYW4gc2VsZWN0IHBvZHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSVBvZFNlbGVjdG9yIGV4dGVuZHMgSUNvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhpcyBzZWxlY3Rvci5cbiAgICovXG4gIHRvUG9kU2VsZWN0b3JDb25maWcoKTogUG9kU2VsZWN0b3JDb25maWc7XG59XG5cbi8qKlxuICogUG9kIGlzIGEgY29sbGVjdGlvbiBvZiBjb250YWluZXJzIHRoYXQgY2FuIHJ1biBvbiBhIGhvc3QuIFRoaXMgcmVzb3VyY2UgaXNcbiAqIGNyZWF0ZWQgYnkgY2xpZW50cyBhbmQgc2NoZWR1bGVkIG9udG8gaG9zdHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBQb2QgZXh0ZW5kcyBBYnN0cmFjdFBvZCB7XG5cbiAgLyoqXG4gICAqIFRoaXMgbGFiZWwgaXMgYXV0b2FtdGljYWxseSBhZGRlZCBieSBjZGs4cyB0byBhbnkgcG9kLiBJdCBwcm92aWRlc1xuICAgKiBhIHVuaXF1ZSBhbmQgc3RhYmxlIGlkZW50aWZpZXIgZm9yIHRoZSBwb2QuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEFERFJFU1NfTEFCRUwgPSAnY2RrOHMuaW8vbWV0YWRhdGEuYWRkcic7XG5cbiAgLyoqXG4gICAqIEBzZWUgYmFzZS5SZXNvdXJjZS5hcGlPYmplY3RcbiAgICovXG4gIHByb3RlY3RlZCByZWFkb25seSBhcGlPYmplY3Q6IEFwaU9iamVjdDtcblxuICBwdWJsaWMgcmVhZG9ubHkgcmVzb3VyY2VUeXBlID0gJ3BvZHMnO1xuXG4gIHB1YmxpYyByZWFkb25seSBzY2hlZHVsaW5nOiBQb2RTY2hlZHVsaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgY29ubmVjdGlvbnM6IFBvZENvbm5lY3Rpb25zO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBQb2RQcm9wcyA9IHt9KSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICB0aGlzLmFwaU9iamVjdCA9IG5ldyBrOHMuS3ViZVBvZCh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBtZXRhZGF0YTogcHJvcHMubWV0YWRhdGEsXG4gICAgICBzcGVjOiBMYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IHRoaXMuX3RvS3ViZSgpIH0pLFxuICAgIH0pO1xuXG4gICAgdGhpcy5tZXRhZGF0YS5hZGRMYWJlbChQb2QuQUREUkVTU19MQUJFTCwgTmFtZXMudG9MYWJlbFZhbHVlKHRoaXMpKTtcblxuICAgIHRoaXMuc2NoZWR1bGluZyA9IG5ldyBQb2RTY2hlZHVsaW5nKHRoaXMpO1xuICAgIHRoaXMuY29ubmVjdGlvbnMgPSBuZXcgUG9kQ29ubmVjdGlvbnModGhpcyk7XG5cbiAgICBpZiAodGhpcy5pc29sYXRlKSB7XG4gICAgICB0aGlzLmNvbm5lY3Rpb25zLmlzb2xhdGUoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0IHBvZE1ldGFkYXRhKCk6IEFwaU9iamVjdE1ldGFkYXRhRGVmaW5pdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMubWV0YWRhdGE7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3RvS3ViZSgpOiBrOHMuUG9kU3BlYyB7XG4gICAgY29uc3Qgc2NoZWR1bGluZyA9IHRoaXMuc2NoZWR1bGluZy5fdG9LdWJlKCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5fdG9Qb2RTcGVjKCksXG4gICAgICBhZmZpbml0eTogc2NoZWR1bGluZy5hZmZpbml0eSxcbiAgICAgIG5vZGVOYW1lOiBzY2hlZHVsaW5nLm5vZGVOYW1lLFxuICAgICAgdG9sZXJhdGlvbnM6IHNjaGVkdWxpbmcudG9sZXJhdGlvbnMsXG4gICAgfTtcbiAgfVxuXG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYFBvZERuc2AuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9kRG5zUHJvcHMge1xuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIGhvc3RuYW1lIG9mIHRoZSBQb2QuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gU2V0IHRvIGEgc3lzdGVtLWRlZmluZWQgdmFsdWUuXG4gICAqL1xuICByZWFkb25seSBob3N0bmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogSWYgc3BlY2lmaWVkLCB0aGUgZnVsbHkgcXVhbGlmaWVkIFBvZCBob3N0bmFtZSB3aWxsIGJlIFwiPGhvc3RuYW1lPi48c3ViZG9tYWluPi48cG9kIG5hbWVzcGFjZT4uc3ZjLjxjbHVzdGVyIGRvbWFpbj5cIi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBzdWJkb21haW4uXG4gICAqL1xuICByZWFkb25seSBzdWJkb21haW4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIElmIHRydWUgdGhlIHBvZCdzIGhvc3RuYW1lIHdpbGwgYmUgY29uZmlndXJlZCBhcyB0aGUgcG9kJ3MgRlFETiwgcmF0aGVyIHRoYW4gdGhlIGxlYWYgbmFtZSAodGhlIGRlZmF1bHQpLlxuICAgKiBJbiBMaW51eCBjb250YWluZXJzLCB0aGlzIG1lYW5zIHNldHRpbmcgdGhlIEZRRE4gaW4gdGhlIGhvc3RuYW1lIGZpZWxkIG9mIHRoZSBrZXJuZWwgKHRoZSBub2RlbmFtZSBmaWVsZCBvZiBzdHJ1Y3QgdXRzbmFtZSkuXG4gICAqIEluIFdpbmRvd3MgY29udGFpbmVycywgdGhpcyBtZWFucyBzZXR0aW5nIHRoZSByZWdpc3RyeSB2YWx1ZSBvZiBob3N0bmFtZSBmb3IgdGhlIHJlZ2lzdHJ5XG4gICAqIGtleSBIS0VZX0xPQ0FMX01BQ0hJTkVcXFNZU1RFTVxcQ3VycmVudENvbnRyb2xTZXRcXFNlcnZpY2VzXFxUY3BpcFxcUGFyYW1ldGVycyB0byBGUUROLlxuICAgKiBJZiBhIHBvZCBkb2VzIG5vdCBoYXZlIEZRRE4sIHRoaXMgaGFzIG5vIGVmZmVjdC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGhvc3RuYW1lQXNGUUROPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogU2V0IEROUyBwb2xpY3kgZm9yIHRoZSBwb2QuXG4gICAqXG4gICAqIElmIHBvbGljeSBpcyBzZXQgdG8gYE5vbmVgLCBvdGhlciBjb25maWd1cmF0aW9uIG11c3QgYmUgc3VwcGxpZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IERuc1BvbGljeS5DTFVTVEVSX0ZJUlNUXG4gICAqL1xuICByZWFkb25seSBwb2xpY3k/OiBEbnNQb2xpY3k7XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBJUCBhZGRyZXNzZXMgdGhhdCB3aWxsIGJlIHVzZWQgYXMgRE5TIHNlcnZlcnMgZm9yIHRoZSBQb2QuIFRoZXJlIGNhbiBiZSBhdCBtb3N0IDMgSVAgYWRkcmVzc2VzIHNwZWNpZmllZC5cbiAgICogV2hlbiB0aGUgcG9saWN5IGlzIHNldCB0byBcIk5PTkVcIiwgdGhlIGxpc3QgbXVzdCBjb250YWluIGF0IGxlYXN0IG9uZSBJUCBhZGRyZXNzLFxuICAgKiBvdGhlcndpc2UgdGhpcyBwcm9wZXJ0eSBpcyBvcHRpb25hbC5cbiAgICogVGhlIHNlcnZlcnMgbGlzdGVkIHdpbGwgYmUgY29tYmluZWQgdG8gdGhlIGJhc2UgbmFtZXNlcnZlcnMgZ2VuZXJhdGVkIGZyb21cbiAgICogdGhlIHNwZWNpZmllZCBETlMgcG9saWN5IHdpdGggZHVwbGljYXRlIGFkZHJlc3NlcyByZW1vdmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZXNlcnZlcnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQSBsaXN0IG9mIEROUyBzZWFyY2ggZG9tYWlucyBmb3IgaG9zdG5hbWUgbG9va3VwIGluIHRoZSBQb2QuXG4gICAqIFdoZW4gc3BlY2lmaWVkLCB0aGUgcHJvdmlkZWQgbGlzdCB3aWxsIGJlIG1lcmdlZCBpbnRvIHRoZSBiYXNlXG4gICAqIHNlYXJjaCBkb21haW4gbmFtZXMgZ2VuZXJhdGVkIGZyb20gdGhlIGNob3NlbiBETlMgcG9saWN5LlxuICAgKiBEdXBsaWNhdGUgZG9tYWluIG5hbWVzIGFyZSByZW1vdmVkLlxuICAgKlxuICAgKiBLdWJlcm5ldGVzIGFsbG93cyBmb3IgYXQgbW9zdCA2IHNlYXJjaCBkb21haW5zLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VhcmNoZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTGlzdCBvZiBvYmplY3RzIHdoZXJlIGVhY2ggb2JqZWN0IG1heSBoYXZlIGEgbmFtZSBwcm9wZXJ0eSAocmVxdWlyZWQpXG4gICAqIGFuZCBhIHZhbHVlIHByb3BlcnR5IChvcHRpb25hbCkuIFRoZSBjb250ZW50cyBpbiB0aGlzIHByb3BlcnR5XG4gICAqIHdpbGwgYmUgbWVyZ2VkIHRvIHRoZSBvcHRpb25zIGdlbmVyYXRlZCBmcm9tIHRoZSBzcGVjaWZpZWQgRE5TIHBvbGljeS5cbiAgICogRHVwbGljYXRlIGVudHJpZXMgYXJlIHJlbW92ZWQuXG4gICAqL1xuICByZWFkb25seSBvcHRpb25zPzogRG5zT3B0aW9uW107XG59XG5cbi8qKlxuICogSG9sZHMgZG5zIHNldHRpbmdzIG9mIHRoZSBwb2QuXG4gKi9cbmV4cG9ydCBjbGFzcyBQb2REbnMge1xuXG4gIC8qKlxuICAgKiBUaGUgRE5TIHBvbGljeSBvZiB0aGlzIHBvZC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwb2xpY3k6IERuc1BvbGljeTtcblxuICAvKipcbiAgICogVGhlIGNvbmZpZ3VyZWQgaG9zdG5hbWUgb2YgdGhlIHBvZC4gVW5kZWZpbmVkIG1lYW5zIGl0cyBzZXQgdG8gYSBzeXN0ZW0tZGVmaW5lZCB2YWx1ZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBob3N0bmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGNvbmZpZ3VyZWQgc3ViZG9tYWluIG9mIHRoZSBwb2QuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc3ViZG9tYWluPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgcG9kcyBob3N0bmFtZSBpcyBzZXQgdG8gaXRzIEZRRE4uXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaG9zdG5hbWVBc0ZRRE46IGJvb2xlYW47XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfbmFtZXNlcnZlcnM6IHN0cmluZ1tdO1xuICBwcml2YXRlIHJlYWRvbmx5IF9zZWFyY2hlczogc3RyaW5nW107XG4gIHByaXZhdGUgcmVhZG9ubHkgX29wdGlvbnM6IERuc09wdGlvbltdO1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBQb2REbnNQcm9wcyA9IHt9KSB7XG4gICAgdGhpcy5ob3N0bmFtZSA9IHByb3BzLmhvc3RuYW1lO1xuICAgIHRoaXMuc3ViZG9tYWluID0gcHJvcHMuc3ViZG9tYWluO1xuICAgIHRoaXMucG9saWN5ID0gcHJvcHMucG9saWN5ID8/IERuc1BvbGljeS5DTFVTVEVSX0ZJUlNUO1xuICAgIHRoaXMuaG9zdG5hbWVBc0ZRRE4gPSBwcm9wcy5ob3N0bmFtZUFzRlFETiA/PyBmYWxzZTtcbiAgICB0aGlzLl9uYW1lc2VydmVycyA9IHByb3BzLm5hbWVzZXJ2ZXJzID8/IFtdO1xuICAgIHRoaXMuX3NlYXJjaGVzID0gcHJvcHMuc2VhcmNoZXMgPz8gW107XG4gICAgdGhpcy5fb3B0aW9ucyA9IHByb3BzLm9wdGlvbnMgPz8gW107XG4gIH1cblxuICAvKipcbiAgICogTmFtZXNlcnZlcnMgZGVmaW5lZCBmb3IgdGhpcyBwb2QuXG4gICAqL1xuICBwdWJsaWMgZ2V0IG5hbWVzZXJ2ZXJzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gWy4uLnRoaXMuX25hbWVzZXJ2ZXJzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZWFyY2ggZG9tYWlucyBkZWZpbmVkIGZvciB0aGlzIHBvZC5cbiAgICovXG4gIHB1YmxpYyBnZXQgc2VhcmNoZXMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5fc2VhcmNoZXNdO1xuICB9XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBkbnMgb3B0aW9ucyBkZWZpbmVkIGZvciB0aGlzIHBvZC5cbiAgICovXG4gIHB1YmxpYyBnZXQgb3B0aW9ucygpOiBEbnNPcHRpb25bXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLl9vcHRpb25zXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBuYW1lc2VydmVyLlxuICAgKi9cbiAgcHVibGljIGFkZE5hbWVzZXJ2ZXIoLi4ubmFtZXNlcnZlcnM6IHN0cmluZ1tdKSB7XG4gICAgdGhpcy5fbmFtZXNlcnZlcnMucHVzaCguLi5uYW1lc2VydmVycyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgc2VhcmNoIGRvbWFpbi5cbiAgICovXG4gIHB1YmxpYyBhZGRTZWFyY2goLi4uc2VhcmNoZXM6IHN0cmluZ1tdKSB7XG4gICAgdGhpcy5fc2VhcmNoZXMucHVzaCguLi5zZWFyY2hlcyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgY3VzdG9tIG9wdGlvbi5cbiAgICovXG4gIHB1YmxpYyBhZGRPcHRpb24oLi4ub3B0aW9uczogRG5zT3B0aW9uW10pIHtcbiAgICB0aGlzLl9vcHRpb25zLnB1c2goLi4ub3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3RvS3ViZSgpOiB7XG4gICAgaG9zdG5hbWU/OiBzdHJpbmc7XG4gICAgc3ViZG9tYWluPzogc3RyaW5nO1xuICAgIGhvc3RuYW1lQXNGUUROOiBib29sZWFuO1xuICAgIHBvbGljeTogc3RyaW5nO1xuICAgIGNvbmZpZzogazhzLlBvZERuc0NvbmZpZztcbiAgfSB7XG5cbiAgICBpZiAodGhpcy5wb2xpY3kgPT09IERuc1BvbGljeS5OT05FICYmIHRoaXMubmFtZXNlcnZlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1doZW4gZG5zIHBvbGljeSBpcyBzZXQgdG8gTk9ORSwgYXQgbGVhc3Qgb25lIG5hbWVzZXJ2ZXIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5uYW1lc2VydmVycy5sZW5ndGggPiAzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGNhbiBiZSBhdCBtb3N0IDMgbmFtZXNlcnZlcnMgc3BlY2lmaWVkJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2VhcmNoZXMubGVuZ3RoID4gNikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGVyZSBjYW4gYmUgYXQgbW9zdCA2IHNlYXJjaCBkb21haW5zIHNwZWNpZmllZCcpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBob3N0bmFtZTogdGhpcy5ob3N0bmFtZSxcbiAgICAgIHN1YmRvbWFpbjogdGhpcy5zdWJkb21haW4sXG4gICAgICBob3N0bmFtZUFzRlFETjogdGhpcy5ob3N0bmFtZUFzRlFETixcbiAgICAgIHBvbGljeTogdGhpcy5wb2xpY3ksXG4gICAgICBjb25maWc6IHtcbiAgICAgICAgbmFtZXNlcnZlcnM6IHVuZGVmaW5lZElmRW1wdHkodGhpcy5uYW1lc2VydmVycyksXG4gICAgICAgIHNlYXJjaGVzOiB1bmRlZmluZWRJZkVtcHR5KHRoaXMuc2VhcmNoZXMpLFxuICAgICAgICBvcHRpb25zOiB1bmRlZmluZWRJZkVtcHR5KHRoaXMub3B0aW9ucyksXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxufVxuXG4vKipcbiAqIEhvbGRzIHBvZC1sZXZlbCBzZWN1cml0eSBhdHRyaWJ1dGVzIGFuZCBjb21tb24gY29udGFpbmVyIHNldHRpbmdzLlxuICovXG5leHBvcnQgY2xhc3MgUG9kU2VjdXJpdHlDb250ZXh0IHtcblxuICBwdWJsaWMgcmVhZG9ubHkgZW5zdXJlTm9uUm9vdDogYm9vbGVhbjtcbiAgcHVibGljIHJlYWRvbmx5IHVzZXI/OiBudW1iZXI7XG4gIHB1YmxpYyByZWFkb25seSBncm91cD86IG51bWJlcjtcbiAgcHVibGljIHJlYWRvbmx5IGZzR3JvdXA/OiBudW1iZXI7XG4gIHB1YmxpYyByZWFkb25seSBmc0dyb3VwQ2hhbmdlUG9saWN5OiBGc0dyb3VwQ2hhbmdlUG9saWN5O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3N5c2N0bHM6IFN5c2N0bFtdID0gW107XG5cbiAgY29uc3RydWN0b3IocHJvcHM6IFBvZFNlY3VyaXR5Q29udGV4dFByb3BzID0ge30pIHtcbiAgICB0aGlzLmVuc3VyZU5vblJvb3QgPSBwcm9wcy5lbnN1cmVOb25Sb290ID8/IHRydWU7XG4gICAgdGhpcy5mc0dyb3VwQ2hhbmdlUG9saWN5ID0gcHJvcHMuZnNHcm91cENoYW5nZVBvbGljeSA/PyBGc0dyb3VwQ2hhbmdlUG9saWN5LkFMV0FZUztcbiAgICB0aGlzLnVzZXIgPSBwcm9wcy51c2VyO1xuICAgIHRoaXMuZ3JvdXAgPSBwcm9wcy5ncm91cDtcbiAgICB0aGlzLmZzR3JvdXAgPSBwcm9wcy5mc0dyb3VwO1xuXG4gICAgZm9yIChjb25zdCBzeXNjdGwgb2YgcHJvcHMuc3lzY3RscyA/PyBbXSkge1xuICAgICAgdGhpcy5fc3lzY3Rscy5wdXNoKHN5c2N0bCk7XG4gICAgfVxuXG4gIH1cblxuICBwdWJsaWMgZ2V0IHN5c2N0bHMoKTogU3lzY3RsW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5fc3lzY3Rsc107XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3RvS3ViZSgpOiBrOHMuUG9kU2VjdXJpdHlDb250ZXh0IHtcbiAgICByZXR1cm4ge1xuICAgICAgcnVuQXNHcm91cDogdGhpcy5ncm91cCxcbiAgICAgIHJ1bkFzVXNlcjogdGhpcy51c2VyLFxuICAgICAgZnNHcm91cDogdGhpcy5mc0dyb3VwLFxuICAgICAgcnVuQXNOb25Sb290OiB0aGlzLmVuc3VyZU5vblJvb3QsXG4gICAgICBmc0dyb3VwQ2hhbmdlUG9saWN5OiB0aGlzLmZzR3JvdXBDaGFuZ2VQb2xpY3ksXG4gICAgICBzeXNjdGxzOiB1bmRlZmluZWRJZkVtcHR5KHRoaXMuX3N5c2N0bHMpLFxuICAgIH07XG4gIH1cblxufVxuXG4vKipcbiAqIFJlc3RhcnQgcG9saWN5IGZvciBhbGwgY29udGFpbmVycyB3aXRoaW4gdGhlIHBvZC5cbiAqL1xuZXhwb3J0IGVudW0gUmVzdGFydFBvbGljeSB7XG4gIC8qKlxuICAgKiBBbHdheXMgcmVzdGFydCB0aGUgcG9kIGFmdGVyIGl0IGV4aXRzLlxuICAgKi9cbiAgQUxXQVlTID0gJ0Fsd2F5cycsXG5cbiAgLyoqXG4gICAqIE9ubHkgcmVzdGFydCBpZiB0aGUgcG9kIGV4aXRzIHdpdGggYSBub24temVybyBleGl0IGNvZGUuXG4gICAqL1xuICBPTl9GQUlMVVJFID0gJ09uRmFpbHVyZScsXG5cbiAgLyoqXG4gICAqIE5ldmVyIHJlc3RhcnQgdGhlIHBvZC5cbiAgICovXG4gIE5FVkVSID0gJ05ldmVyJyxcbn1cblxuZXhwb3J0IGVudW0gRnNHcm91cENoYW5nZVBvbGljeSB7XG5cbiAgLyoqXG4gICAqIE9ubHkgY2hhbmdlIHBlcm1pc3Npb25zIGFuZCBvd25lcnNoaXAgaWYgcGVybWlzc2lvbiBhbmQgb3duZXJzaGlwIG9mIHJvb3QgZGlyZWN0b3J5IGRvZXNcbiAgICogbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgcGVybWlzc2lvbnMgb2YgdGhlIHZvbHVtZS5cbiAgICogVGhpcyBjb3VsZCBoZWxwIHNob3J0ZW4gdGhlIHRpbWUgaXQgdGFrZXMgdG8gY2hhbmdlIG93bmVyc2hpcCBhbmQgcGVybWlzc2lvbiBvZiBhIHZvbHVtZVxuICAgKi9cbiAgT05fUk9PVF9NSVNNQVRDSCA9ICdPblJvb3RNaXNtYXRjaCcsXG5cbiAgLyoqXG4gICAqIEFsd2F5cyBjaGFuZ2UgcGVybWlzc2lvbiBhbmQgb3duZXJzaGlwIG9mIHRoZSB2b2x1bWUgd2hlbiB2b2x1bWUgaXMgbW91bnRlZC5cbiAgICovXG4gIEFMV0FZUyA9ICdBbHdheXMnLFxufVxuXG4vKipcbiAqIEN1c3RvbSBETlMgb3B0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERuc09wdGlvbiB7XG5cbiAgLyoqXG4gICAqIE9wdGlvbiBuYW1lLlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBPcHRpb24gdmFsdWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gdmFsdWUuXG4gICAqL1xuICByZWFkb25seSB2YWx1ZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQb2QgRE5TIHBvbGljaWVzLlxuICovXG5leHBvcnQgZW51bSBEbnNQb2xpY3kge1xuXG4gIC8qKlxuICAgKiBBbnkgRE5TIHF1ZXJ5IHRoYXQgZG9lcyBub3QgbWF0Y2ggdGhlIGNvbmZpZ3VyZWQgY2x1c3RlciBkb21haW4gc3VmZml4LFxuICAgKiBzdWNoIGFzIFwid3d3Lmt1YmVybmV0ZXMuaW9cIiwgaXMgZm9yd2FyZGVkIHRvIHRoZVxuICAgKiB1cHN0cmVhbSBuYW1lc2VydmVyIGluaGVyaXRlZCBmcm9tIHRoZSBub2RlLlxuICAgKiBDbHVzdGVyIGFkbWluaXN0cmF0b3JzIG1heSBoYXZlIGV4dHJhIHN0dWItZG9tYWluIGFuZCB1cHN0cmVhbSBETlMgc2VydmVycyBjb25maWd1cmVkLlxuICAgKi9cbiAgQ0xVU1RFUl9GSVJTVCA9ICdDbHVzdGVyRmlyc3QnLFxuXG4gIC8qKlxuICAgKiBGb3IgUG9kcyBydW5uaW5nIHdpdGggaG9zdE5ldHdvcmssIHlvdSBzaG91bGRcbiAgICogZXhwbGljaXRseSBzZXQgaXRzIEROUyBwb2xpY3kgXCJDbHVzdGVyRmlyc3RXaXRoSG9zdE5ldFwiLlxuICAgKi9cbiAgQ0xVU1RFUl9GSVJTVF9XSVRIX0hPU1RfTkVUID0gJ0NsdXN0ZXJGaXJzdFdpdGhIb3N0TmV0JyxcblxuICAvKipcbiAgICogVGhlIFBvZCBpbmhlcml0cyB0aGUgbmFtZSByZXNvbHV0aW9uIGNvbmZpZ3VyYXRpb25cbiAgICogZnJvbSB0aGUgbm9kZSB0aGF0IHRoZSBwb2RzIHJ1biBvbi5cbiAgICovXG4gIERFRkFVTFQgPSAnRGVmYXVsdCcsXG5cbiAgLyoqXG4gICAqIEl0IGFsbG93cyBhIFBvZCB0byBpZ25vcmUgRE5TIHNldHRpbmdzIGZyb20gdGhlIEt1YmVybmV0ZXMgZW52aXJvbm1lbnQuXG4gICAqIEFsbCBETlMgc2V0dGluZ3MgYXJlIHN1cHBvc2VkIHRvIGJlIHByb3ZpZGVkIHVzaW5nIHRoZSBkbnNDb25maWdcbiAgICogZmllbGQgaW4gdGhlIFBvZCBTcGVjLlxuICAgKi9cbiAgTk9ORSA9ICdOb25lJyxcblxufVxuXG4vKipcbiAqIEhvc3RBbGlhcyBob2xkcyB0aGUgbWFwcGluZyBiZXR3ZWVuIElQIGFuZCBob3N0bmFtZXMgdGhhdCB3aWxsIGJlIGluamVjdGVkIGFzXG4gKiBhbiBlbnRyeSBpbiB0aGUgcG9kJ3MgL2V0Yy9ob3N0cyBmaWxlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEhvc3RBbGlhcyB7XG4gIC8qKlxuICAgKiBIb3N0bmFtZXMgZm9yIHRoZSBjaG9zZW4gSVAgYWRkcmVzcy5cbiAgICovXG4gIHJlYWRvbmx5IGhvc3RuYW1lczogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIElQIGFkZHJlc3Mgb2YgdGhlIGhvc3QgZmlsZSBlbnRyeS5cbiAgICovXG4gIHJlYWRvbmx5IGlwOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHF1ZXJ5IHRoYXQgY2FuIGJlIHBlcmZvcm1lZCBhZ2FpbnN0IG5vZGVzIHdpdGggbGFiZWxzLlxuICovXG5leHBvcnQgY2xhc3MgTm9kZUxhYmVsUXVlcnkge1xuXG4gIC8qKlxuICAgKiBSZXF1aXJlcyB2YWx1ZSBvZiBsYWJlbCBga2V5YCB0byBlcXVhbCBgdmFsdWVgLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBpcyhrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZykge1xuICAgIHJldHVybiBOb2RlTGFiZWxRdWVyeS5pbihrZXksIFt2YWx1ZV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVpcmVzIHZhbHVlIG9mIGxhYmVsIGBrZXlgIHRvIGJlIG9uZSBvZiBgdmFsdWVzYC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaW4oa2V5OiBzdHJpbmcsIHZhbHVlczogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gbmV3IE5vZGVMYWJlbFF1ZXJ5KGtleSwgJ0luJywgdmFsdWVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1aXJlcyB2YWx1ZSBvZiBsYWJlbCBga2V5YCB0byBiZSBub25lIG9mIGB2YWx1ZXNgLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBub3RJbihrZXk6IHN0cmluZywgdmFsdWVzOiBzdHJpbmdbXSkge1xuICAgIHJldHVybiBuZXcgTm9kZUxhYmVsUXVlcnkoa2V5LCAnTm90SW4nLCB2YWx1ZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVpcmVzIGxhYmVsIGBrZXlgIHRvIGV4aXN0LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBleGlzdHMoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IE5vZGVMYWJlbFF1ZXJ5KGtleSwgJ0V4aXN0cycsIHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWlyZXMgbGFiZWwgYGtleWAgdG8gbm90IGV4aXN0LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBkb2VzTm90RXhpc3Qoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IE5vZGVMYWJlbFF1ZXJ5KGtleSwgJ0RvZXNOb3RFeGlzdCcsIHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWlyZXMgdmFsdWUgb2YgbGFiZWwgYGtleWAgdG8gZ3JlYXRlciB0aGFuIGFsbCBlbGVtZW50cyBpbiBgdmFsdWVzYC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ3Qoa2V5OiBzdHJpbmcsIHZhbHVlczogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gbmV3IE5vZGVMYWJlbFF1ZXJ5KGtleSwgJ0d0JywgdmFsdWVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1aXJlcyB2YWx1ZSBvZiBsYWJlbCBga2V5YCB0byBsZXNzIHRoYW4gYWxsIGVsZW1lbnRzIGluIGB2YWx1ZXNgLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBsdChrZXk6IHN0cmluZywgdmFsdWVzOiBzdHJpbmdbXSkge1xuICAgIHJldHVybiBuZXcgTm9kZUxhYmVsUXVlcnkoa2V5LCAnTHQnLCB2YWx1ZXMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGtleTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3BlcmF0b3I6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHZhbHVlcz86IHN0cmluZ1tdKSB7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3RvS3ViZSgpOiBrOHMuTm9kZVNlbGVjdG9yUmVxdWlyZW1lbnQge1xuICAgIHJldHVybiB7XG4gICAgICBrZXk6IHRoaXMua2V5LFxuICAgICAgb3BlcmF0b3I6IHRoaXMub3BlcmF0b3IsXG4gICAgICB2YWx1ZXM6IHRoaXMudmFsdWVzLFxuICAgIH07XG4gIH1cbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgcXVlcnkgdGhhdCBjYW4gYmUgcGVyZm9ybWVkIGFnYWluc3QgcmVzb3VyY2VzIHdpdGggbGFiZWxzLlxuICovXG5leHBvcnQgY2xhc3MgTGFiZWxFeHByZXNzaW9uIHtcblxuICAvKipcbiAgICogUmVxdWlyZXMgdmFsdWUgb2YgbGFiZWwgYGtleWAgdG8gYmUgb25lIG9mIGB2YWx1ZXNgLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBpbihrZXk6IHN0cmluZywgdmFsdWVzOiBzdHJpbmdbXSkge1xuICAgIHJldHVybiBuZXcgTGFiZWxFeHByZXNzaW9uKGtleSwgJ0luJywgdmFsdWVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1aXJlcyB2YWx1ZSBvZiBsYWJlbCBga2V5YCB0byBiZSBub25lIG9mIGB2YWx1ZXNgLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBub3RJbihrZXk6IHN0cmluZywgdmFsdWVzOiBzdHJpbmdbXSkge1xuICAgIHJldHVybiBuZXcgTGFiZWxFeHByZXNzaW9uKGtleSwgJ05vdEluJywgdmFsdWVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1aXJlcyBsYWJlbCBga2V5YCB0byBleGlzdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZXhpc3RzKGtleTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBMYWJlbEV4cHJlc3Npb24oa2V5LCAnRXhpc3RzJywgdW5kZWZpbmVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1aXJlcyBsYWJlbCBga2V5YCB0byBub3QgZXhpc3QuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGRvZXNOb3RFeGlzdChrZXk6IHN0cmluZykge1xuICAgIHJldHVybiBuZXcgTGFiZWxFeHByZXNzaW9uKGtleSwgJ0RvZXNOb3RFeGlzdCcsIHVuZGVmaW5lZCk7XG4gIH1cblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBrZXk6IHN0cmluZyxcbiAgICBwdWJsaWMgcmVhZG9ubHkgb3BlcmF0b3I6IHN0cmluZyxcbiAgICBwdWJsaWMgcmVhZG9ubHkgdmFsdWVzPzogc3RyaW5nW10pIHtcbiAgfVxuXG59XG5cbi8qKlxuICogVGFpbnQgZWZmZWN0cy5cbiAqL1xuZXhwb3J0IGVudW0gVGFpbnRFZmZlY3Qge1xuICAvKipcbiAgICogVGhpcyBtZWFucyB0aGF0IG5vIHBvZCB3aWxsIGJlIGFibGUgdG8gc2NoZWR1bGVcbiAgICogb250byB0aGUgbm9kZSB1bmxlc3MgaXQgaGFzIGEgbWF0Y2hpbmcgdG9sZXJhdGlvbi5cbiAgICovXG4gIE5PX1NDSEVEVUxFID0gJ05vU2NoZWR1bGUnLFxuXG4gIC8qKlxuICAgKiBUaGlzIGlzIGEgXCJwcmVmZXJlbmNlXCIgb3IgXCJzb2Z0XCIgdmVyc2lvbiBvZiBgTk9fU0NIRURVTEVgIC0tIHRoZSBzeXN0ZW1cbiAgICogd2lsbCB0cnkgdG8gYXZvaWQgcGxhY2luZyBhIHBvZCB0aGF0IGRvZXMgbm90IHRvbGVyYXRlIHRoZSB0YWludCBvbiB0aGUgbm9kZSxcbiAgICogYnV0IGl0IGlzIG5vdCByZXF1aXJlZFxuICAgKi9cbiAgUFJFRkVSX05PX1NDSEVEVUxFID0gJ1ByZWZlck5vU2NoZWR1bGUnLFxuXG4gIC8qKlxuICAgKiBUaGlzIGFmZmVjdHMgcG9kcyB0aGF0IGFyZSBhbHJlYWR5IHJ1bm5pbmcgb24gdGhlIG5vZGUgYXMgZm9sbG93czpcbiAgICpcbiAgICogLSBQb2RzIHRoYXQgZG8gbm90IHRvbGVyYXRlIHRoZSB0YWludCBhcmUgZXZpY3RlZCBpbW1lZGlhdGVseS5cbiAgICogLSBQb2RzIHRoYXQgdG9sZXJhdGUgdGhlIHRhaW50IHdpdGhvdXQgc3BlY2lmeWluZyBgZHVyYXRpb25gIHJlbWFpbiBib3VuZCBmb3JldmVyLlxuICAgKiAtIFBvZHMgdGhhdCB0b2xlcmF0ZSB0aGUgdGFpbnQgd2l0aCBhIHNwZWNpZmllZCBgZHVyYXRpb25gIHJlbWFpbiBib3VuZCBmb3JcbiAgICogICB0aGUgc3BlY2lmaWVkIGFtb3VudCBvZiB0aW1lLlxuICAgKi9cbiAgTk9fRVhFQ1VURSA9ICdOb0V4ZWN1dGUnLFxufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGBOb2RlVGFpbnRRdWVyeWAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZVRhaW50UXVlcnlPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSB0YWludCBlZmZlY3QgdG8gbWF0Y2guXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYWxsIGVmZmVjdHMgYXJlIG1hdGNoZWQuXG4gICAqL1xuICByZWFkb25seSBlZmZlY3Q/OiBUYWludEVmZmVjdDtcblxuICAvKipcbiAgICogSG93IG11Y2ggdGltZSBzaG91bGQgYSBwb2QgdGhhdCB0b2xlcmF0ZXMgdGhlIGBOT19FWEVDVVRFYCBlZmZlY3RcbiAgICogYmUgYm91bmQgdG8gdGhlIG5vZGUuIE9ubHkgYXBwbGllcyBmb3IgdGhlIGBOT19FWEVDVVRFYCBlZmZlY3QuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYm91bmQgZm9yZXZlci5cbiAgICovXG4gIHJlYWRvbmx5IGV2aWN0QWZ0ZXI/OiBEdXJhdGlvbjtcbn1cblxuLyoqXG4gKiBUYWludCBxdWVyaWVzIHRoYXQgY2FuIGJlIHBlcmZvbWVkIGFnYWluc3Qgbm9kZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBOb2RlVGFpbnRRdWVyeSB7XG5cbiAgLyoqXG4gICAqIE1hdGNoZXMgYSB0YWludCB3aXRoIGEgc3BlY2lmaWMga2V5IGFuZCB2YWx1ZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaXMoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIG9wdGlvbnM6IE5vZGVUYWludFF1ZXJ5T3B0aW9ucyA9IHt9KTogTm9kZVRhaW50UXVlcnkge1xuICAgIHJldHVybiBuZXcgTm9kZVRhaW50UXVlcnkoJ0VxdWFsJywga2V5LCB2YWx1ZSwgb3B0aW9ucy5lZmZlY3QsIG9wdGlvbnMuZXZpY3RBZnRlcik7XG4gIH1cblxuICAvKipcbiAgICogTWF0Y2hlcyBhIHRhaW4gd2l0aCBhbnkgdmFsdWUgb2YgYSBzcGVjaWZpYyBrZXkuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGV4aXN0cyhrZXk6IHN0cmluZywgb3B0aW9uczogTm9kZVRhaW50UXVlcnlPcHRpb25zID0ge30pOiBOb2RlVGFpbnRRdWVyeSB7XG4gICAgcmV0dXJuIG5ldyBOb2RlVGFpbnRRdWVyeSgnRXhpc3RzJywga2V5LCB1bmRlZmluZWQsIG9wdGlvbnMuZWZmZWN0LCBvcHRpb25zLmV2aWN0QWZ0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hdGNoZXMgYW55IHRhaW50LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhbnkoKTogTm9kZVRhaW50UXVlcnkge1xuICAgIHJldHVybiBuZXcgTm9kZVRhaW50UXVlcnkoJ0V4aXN0cycpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wZXJhdG9yOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBrZXk/OiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSB2YWx1ZT86IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGVmZmVjdD86IFRhaW50RWZmZWN0LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZXZpY3RBZnRlcj86IER1cmF0aW9uLFxuICApIHtcbiAgICBpZiAoZXZpY3RBZnRlciAmJiBlZmZlY3QgIT09IFRhaW50RWZmZWN0Lk5PX0VYRUNVVEUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25seSBcXCdOT19FWEVDVVRFXFwnIGVmZmVjdHMgY2FuIHNwZWNpZnkgXFwnZXZpY3RBZnRlclxcJycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBfdG9LdWJlKCk6IGs4cy5Ub2xlcmF0aW9uIHtcblxuICAgIHJldHVybiB7XG4gICAgICBlZmZlY3Q6IHRoaXMuZWZmZWN0LFxuICAgICAga2V5OiB0aGlzLmtleSxcbiAgICAgIG9wZXJhdG9yOiB0aGlzLm9wZXJhdG9yLFxuICAgICAgdG9sZXJhdGlvblNlY29uZHM6IHRoaXMuZXZpY3RBZnRlcj8udG9TZWNvbmRzKCksXG4gICAgICB2YWx1ZTogdGhpcy52YWx1ZSxcbiAgICB9O1xuICB9XG5cbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgUG9kcy5hbGxgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBvZHNBbGxPcHRpb25zIHtcblxuICAvKipcbiAgICogTmFtZXNwYWNlcyB0aGUgcG9kcyBhcmUgYWxsb3dlZCB0byBiZSBpbi5cbiAgICogVXNlIGBOYW1lc3BhY2VzLmFsbCgpYCB0byBhbGxvdyBhbGwgbmFtZXNwYWNlcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB1bnNldCwgaW1wbGllcyB0aGUgbmFtZXNwYWNlIG9mIHRoZSByZXNvdXJjZSB0aGlzIHNlbGVjdGlvbiBpcyB1c2VkIGluLlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZXNwYWNlcz86IG5hbWVzcGFjZS5OYW1lc3BhY2VzO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGBQb2RzLnNlbGVjdGAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9kc1NlbGVjdE9wdGlvbnMge1xuXG4gIC8qKlxuICAgKiBMYWJlbHMgdGhlIHBvZHMgbXVzdCBoYXZlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHN0cmljdCBsYWJlbHMgcmVxdWlyZW1lbnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgbGFiZWxzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogRXhwcmVzc2lvbnMgdGhlIHBvZHMgbXVzdCBzYXRpc2lmeS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBleHByZXNzaW9ucyByZXF1aXJlbWVudHMuXG4gICAqL1xuICByZWFkb25seSBleHByZXNzaW9ucz86IExhYmVsRXhwcmVzc2lvbltdO1xuXG4gIC8qKlxuICAgKiBOYW1lc3BhY2VzIHRoZSBwb2RzIGFyZSBhbGxvd2VkIHRvIGJlIGluLlxuICAgKiBVc2UgYE5hbWVzcGFjZXMuYWxsKClgIHRvIGFsbG93IGFsbCBuYW1lc3BhY2VzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHVuc2V0LCBpbXBsaWVzIHRoZSBuYW1lc3BhY2Ugb2YgdGhlIHJlc291cmNlIHRoaXMgc2VsZWN0aW9uIGlzIHVzZWQgaW4uXG4gICAqL1xuICByZWFkb25seSBuYW1lc3BhY2VzPzogbmFtZXNwYWNlLk5hbWVzcGFjZXM7XG5cbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgZ3JvdXAgb2YgcG9kcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFBvZHMgZXh0ZW5kcyBDb25zdHJ1Y3QgaW1wbGVtZW50cyBJUG9kU2VsZWN0b3Ige1xuXG4gIC8qKlxuICAgKiBTZWxlY3QgcG9kcyBpbiB0aGUgY2x1c3RlciB3aXRoIHZhcmlvdXMgc2VsZWN0b3JzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzZWxlY3Qoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgb3B0aW9uczogUG9kc1NlbGVjdE9wdGlvbnMpOiBQb2RzIHtcbiAgICByZXR1cm4gbmV3IFBvZHMoc2NvcGUsIGlkLCBvcHRpb25zLmV4cHJlc3Npb25zLCBvcHRpb25zLmxhYmVscywgb3B0aW9ucy5uYW1lc3BhY2VzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZWxlY3QgYWxsIHBvZHMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFsbChzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBvcHRpb25zOiBQb2RzQWxsT3B0aW9ucyA9IHt9KSB7XG4gICAgcmV0dXJuIFBvZHMuc2VsZWN0KHNjb3BlLCBpZCwgeyBuYW1lc3BhY2VzOiBvcHRpb25zLm5hbWVzcGFjZXMgfSk7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZXhwcmVzc2lvbnM/OiBMYWJlbEV4cHJlc3Npb25bXSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGxhYmVscz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0sXG4gICAgcHJpdmF0ZSByZWFkb25seSBuYW1lc3BhY2VzPzogbmFtZXNwYWNlLklOYW1lc3BhY2VTZWxlY3Rvcikge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gIH1cblxuICAvKipcbiAgICogQHNlZSBJUG9kU2VsZWN0b3IudG9Qb2RTZWxlY3RvckNvbmZpZygpXG4gICAqL1xuICBwdWJsaWMgdG9Qb2RTZWxlY3RvckNvbmZpZygpOiBQb2RTZWxlY3RvckNvbmZpZyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsU2VsZWN0b3I6IExhYmVsU2VsZWN0b3Iub2YoeyBleHByZXNzaW9uczogdGhpcy5leHByZXNzaW9ucywgbGFiZWxzOiB0aGlzLmxhYmVscyB9KSxcbiAgICAgIG5hbWVzcGFjZXM6IHRoaXMubmFtZXNwYWNlcz8udG9OYW1lc3BhY2VTZWxlY3RvckNvbmZpZygpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQHNlZSBJTmV0d29ya1BvbGljeVBlZXIudG9OZXR3b3JrUG9saWN5UGVlckNvbmZpZygpXG4gICAqL1xuICBwdWJsaWMgdG9OZXR3b3JrUG9saWN5UGVlckNvbmZpZygpOiBuZXR3b3JrcG9saWN5Lk5ldHdvcmtQb2xpY3lQZWVyQ29uZmlnIHtcbiAgICByZXR1cm4geyBwb2RTZWxlY3RvcjogdGhpcy50b1BvZFNlbGVjdG9yQ29uZmlnKCkgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc2VlIElOZXR3b3JrUG9saWN5UGVlci50b1BvZFNlbGVjdG9yKClcbiAgICovXG4gIHB1YmxpYyB0b1BvZFNlbGVjdG9yKCk6IElQb2RTZWxlY3RvciB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxufVxuXG4vKipcbiAqIEEgbm9kZSB0aGF0IGlzIG1hdGNoZWQgYnkgbGFiZWwgc2VsZWN0b3JzLlxuICovXG5leHBvcnQgY2xhc3MgTGFiZWxlZE5vZGUge1xuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IGxhYmVsU2VsZWN0b3I6IE5vZGVMYWJlbFF1ZXJ5W10pIHtcbiAgfTtcbn1cblxuLyoqXG4gKiBBIG5vZGUgdGhhdCBpcyBtYXRjaGVkIGJ5IHRhaW50IHNlbGVjdG9ycy5cbiAqL1xuZXhwb3J0IGNsYXNzIFRhaW50ZWROb2RlIHtcbiAgcHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSB0YWludFNlbGVjdG9yOiBOb2RlVGFpbnRRdWVyeVtdKSB7XG4gIH07XG59XG5cbi8qKlxuICogQSBub2RlIHRoYXQgaXMgbWF0Y2hlZCBieSBpdHMgbmFtZS5cbiAqL1xuZXhwb3J0IGNsYXNzIE5hbWVkTm9kZSB7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgbmFtZTogc3RyaW5nKSB7XG4gIH07XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIG5vZGUgaW4gdGhlIGNsdXN0ZXIuXG4gKi9cbmV4cG9ydCBjbGFzcyBOb2RlIHtcblxuICAvKipcbiAgICogTWF0Y2ggYSBub2RlIGJ5IGl0cyBsYWJlbHMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGxhYmVsZWQoLi4ubGFiZWxTZWxlY3RvcjogTm9kZUxhYmVsUXVlcnlbXSk6IExhYmVsZWROb2RlIHtcbiAgICByZXR1cm4gbmV3IExhYmVsZWROb2RlKGxhYmVsU2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hdGNoIGEgbm9kZSBieSBpdHMgbmFtZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgbmFtZWQobm9kZU5hbWU6IHN0cmluZyk6IE5hbWVkTm9kZSB7XG4gICAgcmV0dXJuIG5ldyBOYW1lZE5vZGUobm9kZU5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hdGNoIGEgbm9kZSBieSBpdHMgdGFpbnRzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyB0YWludGVkKC4uLnRhaW50U2VsZWN0b3I6IE5vZGVUYWludFF1ZXJ5W10pOiBUYWludGVkTm9kZSB7XG4gICAgcmV0dXJuIG5ldyBUYWludGVkTm9kZSh0YWludFNlbGVjdG9yKTtcbiAgfVxuXG59XG5cbi8qKlxuICogQXZhaWxhYmxlIHRvcG9sb2d5IGRvbWFpbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBUb3BvbG9neSB7XG5cbiAgLyoqXG4gICAqIEEgaG9zdG5hbWUgcmVwcmVzZW50cyBhIHNpbmdsZSBub2RlIGluIHRoZSBjbHVzdGVyLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8va3ViZXJuZXRlcy5pby9kb2NzL3JlZmVyZW5jZS9sYWJlbHMtYW5ub3RhdGlvbnMtdGFpbnRzLyNrdWJlcm5ldGVzaW9ob3N0bmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBIT1NUTkFNRSA9IG5ldyBUb3BvbG9neSgna3ViZXJuZXRlcy5pby9ob3N0bmFtZScpO1xuXG4gIC8qKlxuICAgKiBBIHpvbmUgcmVwcmVzZW50cyBhIGxvZ2ljYWwgZmFpbHVyZSBkb21haW4uIEl0IGlzIGNvbW1vbiBmb3IgS3ViZXJuZXRlcyBjbHVzdGVycyB0b1xuICAgKiBzcGFuIG11bHRpcGxlIHpvbmVzIGZvciBpbmNyZWFzZWQgYXZhaWxhYmlsaXR5LiBXaGlsZSB0aGUgZXhhY3QgZGVmaW5pdGlvbiBvZiBhIHpvbmUgaXNcbiAgICogbGVmdCB0byBpbmZyYXN0cnVjdHVyZSBpbXBsZW1lbnRhdGlvbnMsIGNvbW1vbiBwcm9wZXJ0aWVzIG9mIGEgem9uZSBpbmNsdWRlIHZlcnkgbG93XG4gICAqIG5ldHdvcmsgbGF0ZW5jeSB3aXRoaW4gYSB6b25lLCBuby1jb3N0IG5ldHdvcmsgdHJhZmZpYyB3aXRoaW4gYSB6b25lLCBhbmQgZmFpbHVyZVxuICAgKiBpbmRlcGVuZGVuY2UgZnJvbSBvdGhlciB6b25lcy4gRm9yIGV4YW1wbGUsIG5vZGVzIHdpdGhpbiBhIHpvbmUgbWlnaHQgc2hhcmUgYSBuZXR3b3JrXG4gICAqIHN3aXRjaCwgYnV0IG5vZGVzIGluIGRpZmZlcmVudCB6b25lcyBzaG91bGQgbm90LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8va3ViZXJuZXRlcy5pby9kb2NzL3JlZmVyZW5jZS9sYWJlbHMtYW5ub3RhdGlvbnMtdGFpbnRzLyN0b3BvbG9neWt1YmVybmV0ZXNpb3pvbmVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgWk9ORSA9IG5ldyBUb3BvbG9neSgndG9wb2xvZ3kua3ViZXJuZXRlcy5pby96b25lJyk7XG5cbiAgLyoqXG4gICAqIEEgcmVnaW9uIHJlcHJlc2VudHMgYSBsYXJnZXIgZG9tYWluLCBtYWRlIHVwIG9mIG9uZSBvciBtb3JlIHpvbmVzLiBJdCBpcyB1bmNvbW1vblxuICAgKiBmb3IgS3ViZXJuZXRlcyBjbHVzdGVycyB0byBzcGFuIG11bHRpcGxlIHJlZ2lvbnMuIFdoaWxlIHRoZSBleGFjdCBkZWZpbml0aW9uIG9mIGFcbiAgICogem9uZSBvciByZWdpb24gaXMgbGVmdCB0byBpbmZyYXN0cnVjdHVyZSBpbXBsZW1lbnRhdGlvbnMsIGNvbW1vbiBwcm9wZXJ0aWVzIG9mIGEgcmVnaW9uXG4gICAqIGluY2x1ZGUgaGlnaGVyIG5ldHdvcmsgbGF0ZW5jeSBiZXR3ZWVuIHRoZW0gdGhhbiB3aXRoaW4gdGhlbSwgbm9uLXplcm8gY29zdCBmb3IgbmV0d29ya1xuICAgKiB0cmFmZmljIGJldHdlZW4gdGhlbSwgYW5kIGZhaWx1cmUgaW5kZXBlbmRlbmNlIGZyb20gb3RoZXIgem9uZXMgb3IgcmVnaW9ucy5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsIG5vZGVzIHdpdGhpbiBhIHJlZ2lvbiBtaWdodCBzaGFyZSBwb3dlciBpbmZyYXN0cnVjdHVyZSAoZS5nLiBhIFVQUyBvciBnZW5lcmF0b3IpLCBidXRcbiAgICogbm9kZXMgaW4gZGlmZmVyZW50IHJlZ2lvbnMgdHlwaWNhbGx5IHdvdWxkIG5vdC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2t1YmVybmV0ZXMuaW8vZG9jcy9yZWZlcmVuY2UvbGFiZWxzLWFubm90YXRpb25zLXRhaW50cy8jdG9wb2xvZ3lrdWJlcm5ldGVzaW9yZWdpb25cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUkVHSU9OID0gbmV3IFRvcG9sb2d5KCd0b3BvbG9neS5rdWJlcm5ldGVzLmlvL3JlZ2lvbicpO1xuXG4gIC8qKlxuICAgKiBDdXN0b20ga2V5IGZvciB0aGUgbm9kZSBsYWJlbCB0aGF0IHRoZSBzeXN0ZW0gdXNlcyB0byBkZW5vdGUgdGhlIHRvcG9sb2d5IGRvbWFpbi5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY3VzdG9tKGtleTogc3RyaW5nKTogVG9wb2xvZ3kge1xuICAgIHJldHVybiBuZXcgVG9wb2xvZ3koa2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IGtleTogc3RyaW5nKSB7XG4gIH07XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYFBvZFNjaGVkdWxpbmcuY29sb2NhdGVgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBvZFNjaGVkdWxpbmdDb2xvY2F0ZU9wdGlvbnMge1xuICAvKipcbiAgICogV2hpY2ggdG9wb2xvZ3kgdG8gY29sb2F0ZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBUb3BvbG9neS5IT1NUTkFNRVxuICAgKi9cbiAgcmVhZG9ubHkgdG9wb2xvZ3k/OiBUb3BvbG9neTtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHRoZSBjby1sb2NhdGlvbiBpcyBvcHRpb25hbCAoc29mdCksIHdpdGggdGhpcyB3ZWlnaHQgc2NvcmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gd2VpZ2h0LiBjby1sb2NhdGlvbiBpcyBhc3N1bWVkIHRvIGJlIHJlcXVpcmVkIChoYXJkKS5cbiAgICovXG4gIHJlYWRvbmx5IHdlaWdodD86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgUG9kU2NoZWR1bGluZy5zZXBhcmF0ZWAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9kU2NoZWR1bGluZ1NlcGFyYXRlT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBXaGljaCB0b3BvbG9neSB0byBzZXBhcmF0ZSBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBUb3BvbG9neS5IT1NUTkFNRVxuICAgKi9cbiAgcmVhZG9ubHkgdG9wb2xvZ3k/OiBUb3BvbG9neTtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHRoZSBzZXBhcmF0aW9uIGlzIG9wdGlvbmFsIChzb2Z0KSwgd2l0aCB0aGlzIHdlaWdodCBzY29yZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyB3ZWlnaHQuIHNlcGFyYXRpb24gaXMgYXNzdW1lZCB0byBiZSByZXF1aXJlZCAoaGFyZCkuXG4gICAqL1xuICByZWFkb25seSB3ZWlnaHQ/OiBudW1iZXI7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYFBvZFNjaGVkdWxpbmcuYXR0cmFjdGAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9kU2NoZWR1bGluZ0F0dHJhY3RPcHRpb25zIHtcbiAgLyoqXG4gICAqIEluZGljYXRlcyB0aGUgYXR0cmFjdGlvbiBpcyBvcHRpb25hbCAoc29mdCksIHdpdGggdGhpcyB3ZWlnaHQgc2NvcmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gd2VpZ2h0LiBhc3NpZ25tZW50IGlzIGFzc3VtZWQgdG8gYmUgcmVxdWlyZWQgKGhhcmQpLlxuICAgKi9cbiAgcmVhZG9ubHkgd2VpZ2h0PzogbnVtYmVyO1xufVxuXG4vKipcbiAqIENvbnRyb2xzIHRoZSBwb2Qgc2NoZWR1bGluZyBzdHJhdGVneS5cbiAqL1xuZXhwb3J0IGNsYXNzIFBvZFNjaGVkdWxpbmcge1xuXG4gIHByaXZhdGUgX25vZGVBZmZpbml0eVByZWZlcnJlZDogazhzLlByZWZlcnJlZFNjaGVkdWxpbmdUZXJtW10gPSBbXTtcbiAgcHJpdmF0ZSBfbm9kZUFmZmluaXR5UmVxdWlyZWQ6IGs4cy5Ob2RlU2VsZWN0b3JUZXJtW10gPSBbXTtcbiAgcHJpdmF0ZSBfcG9kQWZmaW5pdHlQcmVmZXJyZWQ6IGs4cy5XZWlnaHRlZFBvZEFmZmluaXR5VGVybVtdID0gW107XG4gIHByaXZhdGUgX3BvZEFmZmluaXR5UmVxdWlyZWQ6IGs4cy5Qb2RBZmZpbml0eVRlcm1bXSA9IFtdO1xuICBwcml2YXRlIF9wb2RBbnRpQWZmaW5pdHlQcmVmZXJyZWQ6IGs4cy5XZWlnaHRlZFBvZEFmZmluaXR5VGVybVtdID0gW107XG4gIHByaXZhdGUgX3BvZEFudGlBZmZpbml0eVJlcXVpcmVkOiBrOHMuUG9kQWZmaW5pdHlUZXJtW10gPSBbXTtcbiAgcHJpdmF0ZSBfdG9sZXJhdGlvbnM6IGs4cy5Ub2xlcmF0aW9uW10gPSBbXTtcbiAgcHJpdmF0ZSBfbm9kZU5hbWU/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIHJlYWRvbmx5IGluc3RhbmNlOiBBYnN0cmFjdFBvZCkge1xuICB9XG5cbiAgLyoqXG4gICAqIEFzc2lnbiB0aGlzIHBvZCBhIHNwZWNpZmljIG5vZGUgYnkgbmFtZS5cbiAgICpcbiAgICogVGhlIHNjaGVkdWxlciBpZ25vcmVzIHRoZSBQb2QsIGFuZCB0aGUga3ViZWxldCBvbiB0aGUgbmFtZWQgbm9kZVxuICAgKiB0cmllcyB0byBwbGFjZSB0aGUgUG9kIG9uIHRoYXQgbm9kZS4gT3ZlcnJ1bGVzIGFueSBhZmZpbml0eSBydWxlcyBvZiB0aGUgcG9kLlxuICAgKlxuICAgKiBTb21lIGxpbWl0YXRpb25zIG9mIHN0YXRpYyBhc3NpZ25tZW50IGFyZTpcbiAgICpcbiAgICogLSBJZiB0aGUgbmFtZWQgbm9kZSBkb2VzIG5vdCBleGlzdCwgdGhlIFBvZCB3aWxsIG5vdCBydW4sIGFuZCBpbiBzb21lXG4gICAqICAgY2FzZXMgbWF5IGJlIGF1dG9tYXRpY2FsbHkgZGVsZXRlZC5cbiAgICogLSBJZiB0aGUgbmFtZWQgbm9kZSBkb2VzIG5vdCBoYXZlIHRoZSByZXNvdXJjZXMgdG8gYWNjb21tb2RhdGUgdGhlIFBvZCxcbiAgICogICB0aGUgUG9kIHdpbGwgZmFpbCBhbmQgaXRzIHJlYXNvbiB3aWxsIGluZGljYXRlIHdoeSwgZm9yIGV4YW1wbGUgT3V0T2ZtZW1vcnkgb3IgT3V0T2ZjcHUuXG4gICAqIC0gTm9kZSBuYW1lcyBpbiBjbG91ZCBlbnZpcm9ubWVudHMgYXJlIG5vdCBhbHdheXMgcHJlZGljdGFibGUgb3Igc3RhYmxlLlxuICAgKlxuICAgKiBXaWxsIHRocm93IGlzIHRoZSBwb2QgaXMgYWxyZWFkeSBhc3NpZ25lZCB0byBuYW1lZCBub2RlLlxuICAgKlxuICAgKiBVbmRlciB0aGUgaG9vZCwgdGhpcyBtZXRob2QgdXRpbGl6ZXMgdGhlIGBub2RlTmFtZWAgcHJvcGVydHkuXG4gICAqL1xuICBwdWJsaWMgYXNzaWduKG5vZGU6IE5hbWVkTm9kZSkge1xuXG4gICAgaWYgKHRoaXMuX25vZGVOYW1lKSB7XG4gICAgICAvLyBkaXNhbGxvdyBvdmVycmlkaW5nIGFuIHN0YXRpYyBub2RlIGFzc2lnbm1lbnRcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGFzc2lnbiAke3RoaXMuaW5zdGFuY2UucG9kTWV0YWRhdGEubmFtZX0gdG8gbm9kZSAke25vZGUubmFtZX0uIEl0IGlzIGFscmVhZHkgYXNzaWduZWQgdG8gbm9kZSAke3RoaXMuX25vZGVOYW1lfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9ub2RlTmFtZSA9IG5vZGUubmFtZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWxsb3cgdGhpcyBwb2QgdG8gdG9sZXJhdGUgdGFpbnRzIG1hdGNoaW5nIHRoZXNlIHRvbGVyYXRpb25zLlxuICAgKlxuICAgKiBZb3UgY2FuIHB1dCBtdWx0aXBsZSB0YWludHMgb24gdGhlIHNhbWUgbm9kZSBhbmQgbXVsdGlwbGUgdG9sZXJhdGlvbnMgb24gdGhlIHNhbWUgcG9kLlxuICAgKiBUaGUgd2F5IEt1YmVybmV0ZXMgcHJvY2Vzc2VzIG11bHRpcGxlIHRhaW50cyBhbmQgdG9sZXJhdGlvbnMgaXMgbGlrZSBhIGZpbHRlcjogc3RhcnQgd2l0aFxuICAgKiBhbGwgb2YgYSBub2RlJ3MgdGFpbnRzLCB0aGVuIGlnbm9yZSB0aGUgb25lcyBmb3Igd2hpY2ggdGhlIHBvZCBoYXMgYSBtYXRjaGluZyB0b2xlcmF0aW9uO1xuICAgKiB0aGUgcmVtYWluaW5nIHVuLWlnbm9yZWQgdGFpbnRzIGhhdmUgdGhlIGluZGljYXRlZCBlZmZlY3RzIG9uIHRoZSBwb2QuIEluIHBhcnRpY3VsYXI6XG4gICAqXG4gICAqIC0gaWYgdGhlcmUgaXMgYXQgbGVhc3Qgb25lIHVuLWlnbm9yZWQgdGFpbnQgd2l0aCBlZmZlY3QgTm9TY2hlZHVsZSB0aGVuIEt1YmVybmV0ZXMgd2lsbFxuICAgKiAgIG5vdCBzY2hlZHVsZSB0aGUgcG9kIG9udG8gdGhhdCBub2RlXG4gICAqIC0gaWYgdGhlcmUgaXMgbm8gdW4taWdub3JlZCB0YWludCB3aXRoIGVmZmVjdCBOb1NjaGVkdWxlIGJ1dCB0aGVyZSBpcyBhdCBsZWFzdCBvbmUgdW4taWdub3JlZFxuICAgKiAgIHRhaW50IHdpdGggZWZmZWN0IFByZWZlck5vU2NoZWR1bGUgdGhlbiBLdWJlcm5ldGVzIHdpbGwgdHJ5IHRvIG5vdCBzY2hlZHVsZSB0aGUgcG9kIG9udG8gdGhlIG5vZGVcbiAgICogLSBpZiB0aGVyZSBpcyBhdCBsZWFzdCBvbmUgdW4taWdub3JlZCB0YWludCB3aXRoIGVmZmVjdCBOb0V4ZWN1dGUgdGhlbiB0aGUgcG9kIHdpbGwgYmUgZXZpY3RlZCBmcm9tXG4gICAqICAgdGhlIG5vZGUgKGlmIGl0IGlzIGFscmVhZHkgcnVubmluZyBvbiB0aGUgbm9kZSksIGFuZCB3aWxsIG5vdCBiZSBzY2hlZHVsZWQgb250byB0aGUgbm9kZSAoaWYgaXQgaXNcbiAgICogICBub3QgeWV0IHJ1bm5pbmcgb24gdGhlIG5vZGUpLlxuICAgKlxuICAgKiBVbmRlciB0aGUgaG9vZCwgdGhpcyBtZXRob2QgdXRpbGl6ZXMgdGhlIGB0b2xlcmF0aW9uc2AgcHJvcGVydHkuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvc2NoZWR1bGluZy1ldmljdGlvbi90YWludC1hbmQtdG9sZXJhdGlvbi9cbiAgICovXG4gIHB1YmxpYyB0b2xlcmF0ZShub2RlOiBUYWludGVkTm9kZSkge1xuICAgIGZvciAoY29uc3QgcXVlcnkgb2Ygbm9kZS50YWludFNlbGVjdG9yKSB7XG4gICAgICB0aGlzLl90b2xlcmF0aW9ucy5wdXNoKHF1ZXJ5Ll90b0t1YmUoKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEF0dHJhY3QgdGhpcyBwb2QgdG8gYSBub2RlIG1hdGNoZWQgYnkgc2VsZWN0b3JzLlxuICAgKiBZb3UgY2FuIHNlbGVjdCBhIG5vZGUgYnkgdXNpbmcgYE5vZGUubGFiZWxlZCgpYC5cbiAgICpcbiAgICogQXR0cmFjdGluZyB0byBtdWx0aXBsZSBub2RlcyAoaS5lIGludm9raW5nIHRoaXMgbWV0aG9kIG11bHRpcGxlIHRpbWVzKSBhY3RzIGFzXG4gICAqIGFuIE9SIGNvbmRpdGlvbiwgbWVhbmluZyB0aGUgcG9kIHdpbGwgYmUgYXNzaWduZWQgdG8gZWl0aGVyIG9uZSBvZiB0aGUgbm9kZXMuXG4gICAqXG4gICAqIFVuZGVyIHRoZSBob29kLCB0aGlzIG1ldGhvZCB1dGlsaXplcyB0aGUgYG5vZGVBZmZpbml0eWAgcHJvcGVydHkuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvc2NoZWR1bGluZy1ldmljdGlvbi9hc3NpZ24tcG9kLW5vZGUvI25vZGUtYWZmaW5pdHlcbiAgICovXG4gIHB1YmxpYyBhdHRyYWN0KG5vZGU6IExhYmVsZWROb2RlLCBvcHRpb25zOiBQb2RTY2hlZHVsaW5nQXR0cmFjdE9wdGlvbnMgPSB7fSkge1xuXG4gICAgY29uc3QgdGVybSA9IHRoaXMuY3JlYXRlTm9kZUFmZmluaXR5VGVybShub2RlKTtcblxuICAgIGlmIChvcHRpb25zLndlaWdodCkge1xuICAgICAgdGhpcy52YWxpZGF0ZVdlaWdodChvcHRpb25zLndlaWdodCk7XG4gICAgICB0aGlzLl9ub2RlQWZmaW5pdHlQcmVmZXJyZWQucHVzaCh7IHdlaWdodDogb3B0aW9ucy53ZWlnaHQsIHByZWZlcmVuY2U6IHRlcm0gfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX25vZGVBZmZpbml0eVJlcXVpcmVkLnB1c2godGVybSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvLWxvY2F0ZSB0aGlzIHBvZCB3aXRoIGEgc2NoZWR1bGluZyBzZWxlY3Rpb24uXG4gICAqXG4gICAqIEEgc2VsZWN0aW9uIGNhbiBiZSBvbmUgb2Y6XG4gICAqXG4gICAqIC0gQW4gaW5zdGFuY2Ugb2YgYSBgUG9kYC5cbiAgICogLSBBbiBpbnN0YW5jZSBvZiBhIGBXb3JrbG9hZGAgKGUuZyBgRGVwbG95bWVudGAsIGBTdGF0ZWZ1bFNldGApLlxuICAgKiAtIEFuIHVuLW1hbmFnZWQgcG9kIHRoYXQgY2FuIGJlIHNlbGVjdGVkIHZpYSBgUG9kcy5zZWxlY3QoKWAuXG4gICAqXG4gICAqIENvLWxvY2F0aW5nIHdpdGggbXVsdGlwbGUgc2VsZWN0aW9ucyAoKGkuZSBpbnZva2luZyB0aGlzIG1ldGhvZCBtdWx0aXBsZSB0aW1lcykpIGFjdHMgYXNcbiAgICogYW4gQU5EIGNvbmRpdGlvbi4gbWVhbmluZyB0aGUgcG9kIHdpbGwgYmUgYXNzaWduZWQgdG8gYSBub2RlIHRoYXQgc2F0aXNmaWVzIGFsbFxuICAgKiBzZWxlY3Rpb25zIChpLmUgcnVucyBhdCBsZWFzdCBvbmUgcG9kIHRoYXQgc2F0aXNpZmllcyBlYWNoIHNlbGVjdGlvbikuXG4gICAqXG4gICAqIFVuZGVyIHRoZSBob29kLCB0aGlzIG1ldGhvZCB1dGlsaXplcyB0aGUgYHBvZEFmZmluaXR5YCBwcm9wZXJ0eS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2t1YmVybmV0ZXMuaW8vZG9jcy9jb25jZXB0cy9zY2hlZHVsaW5nLWV2aWN0aW9uL2Fzc2lnbi1wb2Qtbm9kZS8jaW50ZXItcG9kLWFmZmluaXR5LWFuZC1hbnRpLWFmZmluaXR5XG4gICAqL1xuICBwdWJsaWMgY29sb2NhdGUoc2VsZWN0b3I6IElQb2RTZWxlY3Rvciwgb3B0aW9uczogUG9kU2NoZWR1bGluZ0NvbG9jYXRlT3B0aW9ucyA9IHt9KSB7XG5cbiAgICBjb25zdCB0b3BvbG9neSA9IG9wdGlvbnMudG9wb2xvZ3kgPz8gVG9wb2xvZ3kuSE9TVE5BTUU7XG4gICAgY29uc3QgdGVybSA9IHRoaXMuY3JlYXRlUG9kQWZmaW5pdHlUZXJtKHRvcG9sb2d5LCBzZWxlY3Rvcik7XG5cbiAgICBpZiAob3B0aW9ucy53ZWlnaHQpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVXZWlnaHQob3B0aW9ucy53ZWlnaHQpO1xuICAgICAgdGhpcy5fcG9kQWZmaW5pdHlQcmVmZXJyZWQucHVzaCh7IHdlaWdodDogb3B0aW9ucy53ZWlnaHQsIHBvZEFmZmluaXR5VGVybTogdGVybSB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcG9kQWZmaW5pdHlSZXF1aXJlZC5wdXNoKHRlcm0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXBlcmF0ZSB0aGlzIHBvZCBmcm9tIGEgc2NoZWR1bGluZyBzZWxlY3Rpb24uXG4gICAqXG4gICAqIEEgc2VsZWN0aW9uIGNhbiBiZSBvbmUgb2Y6XG4gICAqXG4gICAqIC0gQW4gaW5zdGFuY2Ugb2YgYSBgUG9kYC5cbiAgICogLSBBbiBpbnN0YW5jZSBvZiBhIGBXb3JrbG9hZGAgKGUuZyBgRGVwbG95bWVudGAsIGBTdGF0ZWZ1bFNldGApLlxuICAgKiAtIEFuIHVuLW1hbmFnZWQgcG9kIHRoYXQgY2FuIGJlIHNlbGVjdGVkIHZpYSBgUG9kcy5zZWxlY3QoKWAuXG4gICAqXG4gICAqIFNlcGVyYXRpbmcgZnJvbSBtdWx0aXBsZSBzZWxlY3Rpb25zIGFjdHMgYXMgYW4gQU5EIGNvbmRpdGlvbi4gbWVhbmluZyB0aGUgcG9kXG4gICAqIHdpbGwgbm90IGJlIGFzc2lnbmVkIHRvIGEgbm9kZSB0aGF0IHNhdGlzZmllcyBhbGwgc2VsZWN0aW9ucyAoaS5lIHJ1bnMgYXQgbGVhc3Qgb25lIHBvZCB0aGF0IHNhdGlzaWZpZXMgZWFjaCBzZWxlY3Rpb24pLlxuICAgKlxuICAgKiBVbmRlciB0aGUgaG9vZCwgdGhpcyBtZXRob2QgdXRpbGl6ZXMgdGhlIGBwb2RBbnRpQWZmaW5pdHlgIHByb3BlcnR5LlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8va3ViZXJuZXRlcy5pby9kb2NzL2NvbmNlcHRzL3NjaGVkdWxpbmctZXZpY3Rpb24vYXNzaWduLXBvZC1ub2RlLyNpbnRlci1wb2QtYWZmaW5pdHktYW5kLWFudGktYWZmaW5pdHlcbiAgICovXG4gIHB1YmxpYyBzZXBhcmF0ZShzZWxlY3RvcjogSVBvZFNlbGVjdG9yLCBvcHRpb25zOiBQb2RTY2hlZHVsaW5nU2VwYXJhdGVPcHRpb25zID0ge30pIHtcblxuICAgIGNvbnN0IHRvcG9sb2d5ID0gb3B0aW9ucy50b3BvbG9neSA/PyBUb3BvbG9neS5IT1NUTkFNRTtcbiAgICBjb25zdCB0ZXJtID0gdGhpcy5jcmVhdGVQb2RBZmZpbml0eVRlcm0odG9wb2xvZ3ksIHNlbGVjdG9yKTtcblxuICAgIGlmIChvcHRpb25zLndlaWdodCkge1xuICAgICAgdGhpcy52YWxpZGF0ZVdlaWdodChvcHRpb25zLndlaWdodCk7XG4gICAgICB0aGlzLl9wb2RBbnRpQWZmaW5pdHlQcmVmZXJyZWQucHVzaCh7IHdlaWdodDogb3B0aW9ucy53ZWlnaHQsIHBvZEFmZmluaXR5VGVybTogdGVybSB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcG9kQW50aUFmZmluaXR5UmVxdWlyZWQucHVzaCh0ZXJtKTtcbiAgICB9XG5cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlUG9kQWZmaW5pdHlUZXJtKHRvcG9sb2d5OiBUb3BvbG9neSwgc2VsZWN0b3I6IElQb2RTZWxlY3Rvcik6IGs4cy5Qb2RBZmZpbml0eVRlcm0ge1xuICAgIGNvbnN0IGNvbmZpZyA9IHNlbGVjdG9yLnRvUG9kU2VsZWN0b3JDb25maWcoKTtcbiAgICByZXR1cm4ge1xuICAgICAgdG9wb2xvZ3lLZXk6IHRvcG9sb2d5LmtleSxcbiAgICAgIGxhYmVsU2VsZWN0b3I6IGNvbmZpZy5sYWJlbFNlbGVjdG9yLl90b0t1YmUoKSxcbiAgICAgIG5hbWVzcGFjZVNlbGVjdG9yOiBjb25maWcubmFtZXNwYWNlcz8ubGFiZWxTZWxlY3Rvcj8uX3RvS3ViZSgpLFxuICAgICAgbmFtZXNwYWNlczogY29uZmlnLm5hbWVzcGFjZXM/Lm5hbWVzLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZU5vZGVBZmZpbml0eVRlcm0obm9kZTogTGFiZWxlZE5vZGUpOiBrOHMuTm9kZVNlbGVjdG9yVGVybSB7XG4gICAgcmV0dXJuIHsgbWF0Y2hFeHByZXNzaW9uczogbm9kZS5sYWJlbFNlbGVjdG9yLm1hcChzID0+IHMuX3RvS3ViZSgpKSB9O1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVdlaWdodCh3ZWlnaHQ6IG51bWJlcikge1xuICAgIGlmICh3ZWlnaHQgPCAxIHx8IHdlaWdodCA+IDEwMCkge1xuICAgICAgLy8gaHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvY29uY2VwdHMvc2NoZWR1bGluZy1ldmljdGlvbi9hc3NpZ24tcG9kLW5vZGUvI25vZGUtYWZmaW5pdHktd2VpZ2h0XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgYWZmaW5pdHkgd2VpZ2h0OiAke3dlaWdodH0uIE11c3QgYmUgaW4gcmFuZ2UgMS0xMDBgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3RvS3ViZSgpOiB7IGFmZmluaXR5PzogazhzLkFmZmluaXR5OyBub2RlTmFtZT86IHN0cmluZzsgdG9sZXJhdGlvbnM/OiBrOHMuVG9sZXJhdGlvbltdIH0ge1xuXG4gICAgY29uc3QgYXRMZWFzdE9uZSA9ICguLi5hcnJheXM6IEFycmF5PGFueT5bXSkgPT4ge1xuICAgICAgcmV0dXJuIGFycmF5cy5mbGF0KCkubGVuZ3RoID4gMDtcbiAgICB9O1xuXG4gICAgY29uc3QgaGFzTm9kZUFmZmluaXR5ID0gYXRMZWFzdE9uZSh0aGlzLl9ub2RlQWZmaW5pdHlQcmVmZXJyZWQsIHRoaXMuX25vZGVBZmZpbml0eVJlcXVpcmVkKTtcbiAgICBjb25zdCBoYXNQb2RBZmZpbml0eSA9IGF0TGVhc3RPbmUodGhpcy5fcG9kQWZmaW5pdHlQcmVmZXJyZWQsIHRoaXMuX3BvZEFmZmluaXR5UmVxdWlyZWQpO1xuICAgIGNvbnN0IGhhc1BvZEFudGlBZmZpbnR5ID0gYXRMZWFzdE9uZSh0aGlzLl9wb2RBbnRpQWZmaW5pdHlQcmVmZXJyZWQsIHRoaXMuX3BvZEFudGlBZmZpbml0eVJlcXVpcmVkKTtcbiAgICBjb25zdCBoYXNBZmZpbml0eSA9IGhhc05vZGVBZmZpbml0eSB8fCBoYXNQb2RBZmZpbml0eSB8fCBoYXNQb2RBbnRpQWZmaW50eTtcblxuICAgIHJldHVybiB7XG4gICAgICBhZmZpbml0eTogaGFzQWZmaW5pdHkgPyB7XG4gICAgICAgIG5vZGVBZmZpbml0eTogaGFzTm9kZUFmZmluaXR5ID8ge1xuICAgICAgICAgIHByZWZlcnJlZER1cmluZ1NjaGVkdWxpbmdJZ25vcmVkRHVyaW5nRXhlY3V0aW9uOiB1bmRlZmluZWRJZkVtcHR5KHRoaXMuX25vZGVBZmZpbml0eVByZWZlcnJlZCksXG4gICAgICAgICAgcmVxdWlyZWREdXJpbmdTY2hlZHVsaW5nSWdub3JlZER1cmluZ0V4ZWN1dGlvbjogdGhpcy5fbm9kZUFmZmluaXR5UmVxdWlyZWQubGVuZ3RoID4gMCA/IHtcbiAgICAgICAgICAgIG5vZGVTZWxlY3RvclRlcm1zOiB0aGlzLl9ub2RlQWZmaW5pdHlSZXF1aXJlZCxcbiAgICAgICAgICB9IDogdW5kZWZpbmVkLFxuICAgICAgICB9IDogdW5kZWZpbmVkLFxuICAgICAgICBwb2RBZmZpbml0eTogaGFzUG9kQWZmaW5pdHkgPyB7XG4gICAgICAgICAgcHJlZmVycmVkRHVyaW5nU2NoZWR1bGluZ0lnbm9yZWREdXJpbmdFeGVjdXRpb246IHVuZGVmaW5lZElmRW1wdHkodGhpcy5fcG9kQWZmaW5pdHlQcmVmZXJyZWQpLFxuICAgICAgICAgIHJlcXVpcmVkRHVyaW5nU2NoZWR1bGluZ0lnbm9yZWREdXJpbmdFeGVjdXRpb246IHVuZGVmaW5lZElmRW1wdHkodGhpcy5fcG9kQWZmaW5pdHlSZXF1aXJlZCksXG4gICAgICAgIH0gOiB1bmRlZmluZWQsXG4gICAgICAgIHBvZEFudGlBZmZpbml0eTogaGFzUG9kQW50aUFmZmludHkgPyB7XG4gICAgICAgICAgcHJlZmVycmVkRHVyaW5nU2NoZWR1bGluZ0lnbm9yZWREdXJpbmdFeGVjdXRpb246IHVuZGVmaW5lZElmRW1wdHkodGhpcy5fcG9kQW50aUFmZmluaXR5UHJlZmVycmVkKSxcbiAgICAgICAgICByZXF1aXJlZER1cmluZ1NjaGVkdWxpbmdJZ25vcmVkRHVyaW5nRXhlY3V0aW9uOiB1bmRlZmluZWRJZkVtcHR5KHRoaXMuX3BvZEFudGlBZmZpbml0eVJlcXVpcmVkKSxcbiAgICAgICAgfSA6IHVuZGVmaW5lZCxcbiAgICAgIH0gOiB1bmRlZmluZWQsXG4gICAgICBub2RlTmFtZTogdGhpcy5fbm9kZU5hbWUsXG4gICAgICB0b2xlcmF0aW9uczogdW5kZWZpbmVkSWZFbXB0eSh0aGlzLl90b2xlcmF0aW9ucyksXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIElzb2xhdGlvbiBkZXRlcm1pbmVzIHdoaWNoIHBvbGljaWVzIGFyZSBjcmVhdGVkXG4gKiB3aGVuIGFsbG93aW5nIGNvbm5lY3Rpb25zIGZyb20gYSBhIHBvZCAvIHdvcmtsb2FkIHRvIHBlZXJzLlxuICovXG5leHBvcnQgZW51bSBQb2RDb25uZWN0aW9uc0lzb2xhdGlvbiB7XG5cbiAgLyoqXG4gICAqIE9ubHkgY3JlYXRlcyBuZXR3b3JrIHBvbGljaWVzIHRoYXQgc2VsZWN0IHRoZSBwb2QuXG4gICAqL1xuICBQT0QgPSAnUE9EJyxcblxuICAvKipcbiAgICogT25seSBjcmVhdGVzIG5ldHdvcmsgcG9saWNpZXMgdGhhdCBzZWxlY3QgdGhlIHBlZXIuXG4gICAqL1xuICBQRUVSID0gJ1BFRVInLFxuXG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYFBvZENvbm5lY3Rpb25zLmFsbG93VG9gLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBvZENvbm5lY3Rpb25zQWxsb3dUb09wdGlvbnMge1xuXG4gIC8qKlxuICAgKiBXaGljaCBpc29sYXRpb24gc2hvdWxkIGJlIGFwcGxpZWQgdG8gZXN0YWJsaXNoIHRoZSBjb25uZWN0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHVuc2V0LCBpc29sYXRlcyBib3RoIHRoZSBwb2QgYW5kIHRoZSBwZWVyLlxuICAgKi9cbiAgcmVhZG9ubHkgaXNvbGF0aW9uPzogUG9kQ29ubmVjdGlvbnNJc29sYXRpb247XG5cbiAgLyoqXG4gICAqIFBvcnRzIHRvIGFsbG93IG91dGdvaW5nIHRyYWZmaWMgdG8uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gSWYgdGhlIHBlZXIgaXMgYSBtYW5hZ2VkIHBvZCwgdGFrZSBpdHMgcG9ydHMuIE90aGVyd2lzZSwgYWxsIHBvcnRzIGFyZSBhbGxvd2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydHM/OiBuZXR3b3JrcG9saWN5Lk5ldHdvcmtQb2xpY3lQb3J0W107XG5cbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBgUG9kQ29ubmVjdGlvbnMuYWxsb3dGcm9tYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQb2RDb25uZWN0aW9uc0FsbG93RnJvbU9wdGlvbnMge1xuXG4gIC8qKlxuICAgKiBXaGljaCBpc29sYXRpb24gc2hvdWxkIGJlIGFwcGxpZWQgdG8gZXN0YWJsaXNoIHRoZSBjb25uZWN0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHVuc2V0LCBpc29sYXRlcyBib3RoIHRoZSBwb2QgYW5kIHRoZSBwZWVyLlxuICAgKi9cbiAgcmVhZG9ubHkgaXNvbGF0aW9uPzogUG9kQ29ubmVjdGlvbnNJc29sYXRpb247XG5cbiAgLyoqXG4gICAqIFBvcnRzIHRvIGFsbG93IGluY29taW5nIHRyYWZmaWMgdG8uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIHBvZCBwb3J0cy5cbiAgICovXG4gIHJlYWRvbmx5IHBvcnRzPzogbmV0d29ya3BvbGljeS5OZXR3b3JrUG9saWN5UG9ydFtdO1xuXG59XG5cbi8qKlxuICogQ29udHJvbHMgbmV0d29yayBpc29sYXRpb24gcnVsZXMgZm9yIGludGVyLXBvZCBjb21tdW5pY2F0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgUG9kQ29ubmVjdGlvbnMge1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCByZWFkb25seSBpbnN0YW5jZTogQWJzdHJhY3RQb2QpIHtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvdyBuZXR3b3JrIHRyYWZmaWMgZnJvbSB0aGlzIHBvZCB0byB0aGUgcGVlci5cbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhpcyB3aWxsIGNyZWF0ZSBhbiBlZ3Jlc3MgbmV0d29yayBwb2xpY3kgZm9yIHRoaXMgcG9kLCBhbmQgYW4gaW5ncmVzc1xuICAgKiBuZXR3b3JrIHBvbGljeSBmb3IgdGhlIHBlZXIuIFRoaXMgaXMgcmVxdWlyZWQgaWYgYm90aCBzaWRlcyBhcmUgYWxyZWFkeSBpc29sYXRlZC5cbiAgICogVXNlIGBvcHRpb25zLmlzb2xhdGlvbmAgdG8gY29udHJvbCB0aGlzIGJlaGF2aW9yLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAvLyBjcmVhdGUgb25seSBhbiBlZ3Jlc3MgcG9saWN5IHRoYXQgc2VsZWN0cyB0aGUgJ3dlYicgcG9kIHRvIGFsbG93IG91dGdvaW5nIHRyYWZmaWNcbiAgICogLy8gdG8gdGhlICdyZWRpcycgcG9kLiB0aGlzIHJlcXVpcmVzIHRoZSAncmVkaXMnIHBvZCB0byBub3QgYmUgaXNvbGF0ZWQgZm9yIGluZ3Jlc3MuXG4gICAqIHdlYi5jb25uZWN0aW9ucy5hbGxvd1RvKHJlZGlzLCB7IGlzb2xhdGlvbjogSXNvbGF0aW9uLlBPRCB9KVxuICAgKlxuICAgKiAvLyBjcmVhdGUgb25seSBhbiBpbmdyZXNzIHBvbGljeSB0aGF0IHNlbGVjdHMgdGhlICdyZWRpcycgcGVlciB0byBhbGxvdyBpbmNvbWluZyB0cmFmZmljXG4gICAqIC8vIGZyb20gdGhlICd3ZWInIHBvZC4gdGhpcyByZXF1aXJlcyB0aGUgJ3dlYicgcG9kIHRvIG5vdCBiZSBpc29sYXRlZCBmb3IgZWdyZXNzLlxuICAgKiB3ZWIuY29ubmVjdGlvbnMuYWxsb3dUbyhyZWRpcywgeyBpc29sYXRpb246IElzb2xhdGlvbi5QRUVSIH0pXG4gICAqXG4gICAqL1xuICBwdWJsaWMgYWxsb3dUbyhwZWVyOiBuZXR3b3JrcG9saWN5LklOZXR3b3JrUG9saWN5UGVlciwgb3B0aW9uczogUG9kQ29ubmVjdGlvbnNBbGxvd1RvT3B0aW9ucyA9IHt9KSB7XG4gICAgcmV0dXJuIHRoaXMuYWxsb3coJ0VncmVzcycsIHBlZXIsIHsgcG9ydHM6IHRoaXMuZXh0cmFjdFBvcnRzKHBlZXIpLCAuLi5vcHRpb25zIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93IG5ldHdvcmsgdHJhZmZpYyBmcm9tIHRoZSBwZWVyIHRvIHRoaXMgcG9kLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCB0aGlzIHdpbGwgY3JlYXRlIGFuIGluZ3Jlc3MgbmV0d29yayBwb2xpY3kgZm9yIHRoaXMgcG9kLCBhbmQgYW4gZWdyZXNzXG4gICAqIG5ldHdvcmsgcG9saWN5IGZvciB0aGUgcGVlci4gVGhpcyBpcyByZXF1aXJlZCBpZiBib3RoIHNpZGVzIGFyZSBhbHJlYWR5IGlzb2xhdGVkLlxuICAgKiBVc2UgYG9wdGlvbnMuaXNvbGF0aW9uYCB0byBjb250cm9sIHRoaXMgYmVoYXZpb3IuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIC8vIGNyZWF0ZSBvbmx5IGFuIGVncmVzcyBwb2xpY3kgdGhhdCBzZWxlY3RzIHRoZSAnd2ViJyBwb2QgdG8gYWxsb3cgb3V0Z29pbmcgdHJhZmZpY1xuICAgKiAvLyB0byB0aGUgJ3JlZGlzJyBwb2QuIHRoaXMgcmVxdWlyZXMgdGhlICdyZWRpcycgcG9kIHRvIG5vdCBiZSBpc29sYXRlZCBmb3IgaW5ncmVzcy5cbiAgICogcmVkaXMuY29ubmVjdGlvbnMuYWxsb3dGcm9tKHdlYiwgeyBpc29sYXRpb246IElzb2xhdGlvbi5QRUVSIH0pXG4gICAqXG4gICAqIC8vIGNyZWF0ZSBvbmx5IGFuIGluZ3Jlc3MgcG9saWN5IHRoYXQgc2VsZWN0cyB0aGUgJ3JlZGlzJyBwZWVyIHRvIGFsbG93IGluY29taW5nIHRyYWZmaWNcbiAgICogLy8gZnJvbSB0aGUgJ3dlYicgcG9kLiB0aGlzIHJlcXVpcmVzIHRoZSAnd2ViJyBwb2QgdG8gbm90IGJlIGlzb2xhdGVkIGZvciBlZ3Jlc3MuXG4gICAqIHJlZGlzLmNvbm5lY3Rpb25zLmFsbG93RnJvbSh3ZWIsIHsgaXNvbGF0aW9uOiBJc29sYXRpb24uUE9EIH0pXG4gICAqXG4gICAqL1xuICBwdWJsaWMgYWxsb3dGcm9tKHBlZXI6IG5ldHdvcmtwb2xpY3kuSU5ldHdvcmtQb2xpY3lQZWVyLCBvcHRpb25zOiBQb2RDb25uZWN0aW9uc0FsbG93RnJvbU9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLmFsbG93KCdJbmdyZXNzJywgcGVlciwgeyBwb3J0czogdGhpcy5leHRyYWN0UG9ydHModGhpcy5pbnN0YW5jZSksIC4uLm9wdGlvbnMgfSk7XG4gIH1cblxuICBwcml2YXRlIGFsbG93KGRpcmVjdGlvbjogJ0luZ3Jlc3MnIHwgJ0VncmVzcycsIHBlZXI6IG5ldHdvcmtwb2xpY3kuSU5ldHdvcmtQb2xpY3lQZWVyLCBvcHRpb25zOiBQb2RDb25uZWN0aW9uc0FsbG93VG9PcHRpb25zIHwgUG9kQ29ubmVjdGlvbnNBbGxvd0Zyb21PcHRpb25zID0ge30pIHtcblxuICAgIGNvbnN0IGNvbmZpZyA9IHBlZXIudG9OZXR3b3JrUG9saWN5UGVlckNvbmZpZygpO1xuICAgIG5ldHdvcmtwb2xpY3kudmFsaWRhdGVQZWVyQ29uZmlnKGNvbmZpZyk7XG5cbiAgICBjb25zdCBwZWVyQWRkcmVzcyA9IGFkZHJlc3MocGVlcik7XG5cbiAgICBpZiAoIW9wdGlvbnMuaXNvbGF0aW9uIHx8IG9wdGlvbnMuaXNvbGF0aW9uID09PSBQb2RDb25uZWN0aW9uc0lzb2xhdGlvbi5QT0QpIHtcblxuICAgICAgY29uc3Qgc3JjID0gbmV3IG5ldHdvcmtwb2xpY3kuTmV0d29ya1BvbGljeSh0aGlzLmluc3RhbmNlLCBgQWxsb3cke2RpcmVjdGlvbn0ke3BlZXJBZGRyZXNzfWAsIHtcbiAgICAgICAgc2VsZWN0b3I6IHRoaXMuaW5zdGFuY2UsXG4gICAgICAgIC8vIHRoZSBwb2xpY3kgbXVzdCBiZSBkZWZpbmVkIGluIHRoZSBuYW1lc3BhY2Ugb2YgdGhlIHBvZFxuICAgICAgICAvLyBzbyBpdCBjYW4gc2VsZWN0IGl0LlxuICAgICAgICBtZXRhZGF0YTogeyBuYW1lc3BhY2U6IHRoaXMuaW5zdGFuY2UubWV0YWRhdGEubmFtZXNwYWNlIH0sXG4gICAgICB9KTtcblxuICAgICAgc3dpdGNoIChkaXJlY3Rpb24pIHtcbiAgICAgICAgY2FzZSAnRWdyZXNzJzpcbiAgICAgICAgICBzcmMuYWRkRWdyZXNzUnVsZShwZWVyLCBvcHRpb25zLnBvcnRzKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnSW5ncmVzcyc6XG4gICAgICAgICAgc3JjLmFkZEluZ3Jlc3NSdWxlKHBlZXIsIG9wdGlvbnMucG9ydHMpO1xuICAgICAgfVxuXG4gICAgfVxuXG4gICAgaWYgKCFvcHRpb25zLmlzb2xhdGlvbiB8fCBvcHRpb25zLmlzb2xhdGlvbiA9PT0gUG9kQ29ubmVjdGlvbnNJc29sYXRpb24uUEVFUikge1xuXG4gICAgICBpZiAoY29uZmlnLmlwQmxvY2spIHtcbiAgICAgICAgLy8gZm9yIGFuIGlwIGJsb2NrIHdlIGRvbid0IG5lZWQgdG8gY3JlYXRlIHRoZSBvcHBvc2l0ZSBwb2xpY2llc1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBvZFNlbGVjdG9yID0gcGVlci50b1BvZFNlbGVjdG9yKCk7XG4gICAgICBpZiAoIXBvZFNlbGVjdG9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGNyZWF0ZSBwb2xpY2llcyBmb3IgcGVlciAnJHtwZWVyLm5vZGUuYWRkcn0nIHNpbmNlIGl0cyBub3QgYSBwb2Qgc2VsZWN0b3JgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3Bwb3NpdGVEaXJlY3Rpb24gPSBkaXJlY3Rpb24gPT09ICdFZ3Jlc3MnID8gJ0luZ3Jlc3MnIDogJ0VncmVzcyc7XG5cbiAgICAgIGNvbnN0IHBvZFNlbGVjdG9yQ29uZmlnID0gcG9kU2VsZWN0b3IudG9Qb2RTZWxlY3RvckNvbmZpZygpO1xuICAgICAgbGV0IG5hbWVzcGFjZXM6IChzdHJpbmcgfCB1bmRlZmluZWQpW107XG5cbiAgICAgIGlmICghcG9kU2VsZWN0b3JDb25maWcubmFtZXNwYWNlcykge1xuXG4gICAgICAgIC8vIGlmIHRoZSBwZWVyIGRvZXNuJ3Qgc3BlY2lmeSBuYW1lc3BhY2VzLCB3ZSBhc3N1bWUgdGhlIHNhbWUgbmFtZXNwYWNlLlxuICAgICAgICBuYW1lc3BhY2VzID0gW3RoaXMuaW5zdGFuY2UubWV0YWRhdGEubmFtZXNwYWNlXTtcblxuICAgICAgfSBlbHNlIHtcblxuICAgICAgICAvLyBhIHBlZXIgY2Fubm90IHNwZWNpZnkgbmFtZXNwYWNlcyBieSBsYWJlbHMgYmVjYXVzZVxuICAgICAgICAvLyB3ZSB3b24ndCBiZSBhYmxlIHRvIGV4dHJhY3QgdGhlIG5hbWVzIG9mIHRob3NlIG5hbWVzcGFjZXMuXG4gICAgICAgIGlmIChwb2RTZWxlY3RvckNvbmZpZy5uYW1lc3BhY2VzLmxhYmVsU2VsZWN0b3IgJiYgIXBvZFNlbGVjdG9yQ29uZmlnLm5hbWVzcGFjZXMubGFiZWxTZWxlY3Rvci5pc0VtcHR5KCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBjcmVhdGUgYW4gJHtvcHBvc2l0ZURpcmVjdGlvbn0gcG9saWN5IGZvciBwZWVyICcke3BlZXIubm9kZS5wYXRofScgKHBvZD0ke3RoaXMuaW5zdGFuY2UubmFtZX0pLiBQZWVyIG11c3Qgc3BlY2lmeSBuYW1lc3BhY2VzIG9ubHkgYnkgbmFtZWApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gYSBwZWVyIG11c3Qgc3BlY2lmeSBuYW1lc3BhY2VzIGJ5IG5hbWUuXG4gICAgICAgIGlmICghcG9kU2VsZWN0b3JDb25maWcubmFtZXNwYWNlcy5uYW1lcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGNyZWF0ZSBhbiAke29wcG9zaXRlRGlyZWN0aW9ufSBwb2xpY3kgZm9yIHBlZXIgJyR7cGVlci5ub2RlLnBhdGh9JyAocG9kPSR7dGhpcy5pbnN0YW5jZS5uYW1lfSkuIFBlZXIgbXVzdCBzcGVjaWZ5IG5hbWVzcGFjZSBuYW1lc2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgbmFtZXNwYWNlcyA9IHBvZFNlbGVjdG9yQ29uZmlnLm5hbWVzcGFjZXMubmFtZXM7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBuYW1lc3BhY2VzKSB7XG4gICAgICAgIHN3aXRjaCAoZGlyZWN0aW9uKSB7XG4gICAgICAgICAgY2FzZSAnRWdyZXNzJzpcbiAgICAgICAgICAgIG5ldyBuZXR3b3JrcG9saWN5Lk5ldHdvcmtQb2xpY3kodGhpcy5pbnN0YW5jZSwgYEFsbG93SW5ncmVzcyR7bmFtZX0ke3BlZXJBZGRyZXNzfWAsIHtcbiAgICAgICAgICAgICAgc2VsZWN0b3I6IHBvZFNlbGVjdG9yLFxuICAgICAgICAgICAgICBtZXRhZGF0YTogeyBuYW1lc3BhY2U6IG5hbWUgfSxcbiAgICAgICAgICAgICAgaW5ncmVzczogeyBydWxlczogW3sgcGVlcjogdGhpcy5pbnN0YW5jZSwgcG9ydHM6IG9wdGlvbnMucG9ydHMgfV0gfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnSW5ncmVzcyc6XG4gICAgICAgICAgICBuZXcgbmV0d29ya3BvbGljeS5OZXR3b3JrUG9saWN5KHRoaXMuaW5zdGFuY2UsIGBBbGxvd0VncmVzcyR7bmFtZX0ke3BlZXJBZGRyZXNzfWAsIHtcbiAgICAgICAgICAgICAgc2VsZWN0b3I6IHBvZFNlbGVjdG9yLFxuICAgICAgICAgICAgICBtZXRhZGF0YTogeyBuYW1lc3BhY2U6IG5hbWUgfSxcbiAgICAgICAgICAgICAgZWdyZXNzOiB7IHJ1bGVzOiBbeyBwZWVyOiB0aGlzLmluc3RhbmNlLCBwb3J0czogb3B0aW9ucy5wb3J0cyB9XSB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkaXJlY3Rpb246ICR7ZGlyZWN0aW9ufWApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGV4dHJhY3RQb3J0cyhzZWxlY3Rvcj86IG5ldHdvcmtwb2xpY3kuSU5ldHdvcmtQb2xpY3lQZWVyKTogbmV0d29ya3BvbGljeS5OZXR3b3JrUG9saWN5UG9ydFtdIHtcbiAgICByZXR1cm4gY29udGFpbmVyLmV4dHJhY3RDb250YWluZXJQb3J0cyhzZWxlY3RvcikubWFwKG4gPT4gbmV0d29ya3BvbGljeS5OZXR3b3JrUG9saWN5UG9ydC50Y3Aobi5udW1iZXIpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBkZWZhdWx0IG5ldHdvcmsgcG9saWN5IGZvciBQb2QvV29ya2xvYWQgdG8gaGF2ZSBhbGwgZWdyZXNzIGFuZCBpbmdyZXNzIGNvbm5lY3Rpb25zIGFzIGRpc2FibGVkXG4gICAqL1xuICBwdWJsaWMgaXNvbGF0ZSgpIHtcbiAgICBuZXcgbmV0d29ya3BvbGljeS5OZXR3b3JrUG9saWN5KHRoaXMuaW5zdGFuY2UsICdEZWZhdWx0RGVueUFsbCcsIHtcbiAgICAgIHNlbGVjdG9yOiB0aGlzLmluc3RhbmNlLFxuICAgICAgLy8gdGhlIHBvbGljeSBtdXN0IGJlIGRlZmluZWQgaW4gdGhlIG5hbWVzcGFjZSBvZiB0aGUgcG9kXG4gICAgICAvLyBzbyBpdCBjYW4gc2VsZWN0IGl0LlxuICAgICAgbWV0YWRhdGE6IHsgbmFtZXNwYWNlOiB0aGlzLmluc3RhbmNlLm1ldGFkYXRhLm5hbWVzcGFjZSB9LFxuICAgICAgZWdyZXNzOiB7XG4gICAgICAgIGRlZmF1bHQ6IG5ldHdvcmtwb2xpY3kuTmV0d29ya1BvbGljeVRyYWZmaWNEZWZhdWx0LkRFTlksXG4gICAgICB9LFxuICAgICAgaW5ncmVzczoge1xuICAgICAgICBkZWZhdWx0OiBuZXR3b3JrcG9saWN5Lk5ldHdvcmtQb2xpY3lUcmFmZmljRGVmYXVsdC5ERU5ZLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuIl19