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