projen 0.67.26 → 0.67.28
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 +624 -135
- package/docs/api/API.md +155 -0
- package/lib/awscdk/auto-discover.js +5 -5
- package/lib/awscdk/awscdk-app-java.js +1 -1
- package/lib/awscdk/awscdk-app-py.js +1 -1
- package/lib/awscdk/awscdk-app-ts.js +1 -1
- package/lib/awscdk/awscdk-construct.js +2 -2
- package/lib/awscdk/awscdk-deps-java.js +1 -1
- package/lib/awscdk/awscdk-deps-js.js +1 -1
- package/lib/awscdk/awscdk-deps-py.js +1 -1
- package/lib/awscdk/awscdk-deps.js +1 -1
- package/lib/awscdk/cdk-config.js +1 -1
- package/lib/awscdk/cdk-tasks.js +1 -1
- package/lib/awscdk/integration-test.js +1 -1
- package/lib/awscdk/lambda-extension.js +1 -1
- package/lib/awscdk/lambda-function.js +2 -2
- package/lib/build/build-workflow.js +1 -1
- package/lib/cdk/auto-discover-base.js +2 -2
- package/lib/cdk/construct-lib.js +1 -1
- package/lib/cdk/integration-test-base.js +1 -1
- package/lib/cdk/jsii-docgen.js +1 -1
- package/lib/cdk/jsii-project.js +1 -1
- package/lib/cdk8s/auto-discover.js +2 -2
- package/lib/cdk8s/cdk8s-app-py.js +1 -1
- package/lib/cdk8s/cdk8s-app-ts.js +1 -1
- package/lib/cdk8s/cdk8s-construct.js +1 -1
- package/lib/cdk8s/cdk8s-deps-py.js +1 -1
- package/lib/cdk8s/cdk8s-deps.js +1 -1
- package/lib/cdk8s/integration-test.js +1 -1
- package/lib/cdktf/cdktf-construct.js +1 -1
- package/lib/circleci/circleci.js +1 -1
- package/lib/component.js +1 -1
- package/lib/dependencies.js +1 -1
- package/lib/dev-env.js +1 -1
- package/lib/docker-compose/docker-compose-network.d.ts +103 -0
- package/lib/docker-compose/docker-compose-network.js +3 -0
- package/lib/docker-compose/docker-compose-port.d.ts +44 -0
- package/lib/docker-compose/docker-compose-port.js +18 -0
- package/lib/docker-compose/docker-compose-render.d.ts +2 -0
- package/lib/docker-compose/docker-compose-render.js +129 -0
- package/lib/docker-compose/docker-compose-service.d.ts +132 -0
- package/lib/docker-compose/docker-compose-service.js +68 -0
- package/lib/docker-compose/docker-compose-volume.d.ts +64 -0
- package/lib/docker-compose/docker-compose-volume.js +3 -0
- package/lib/docker-compose/docker-compose.d.ts +99 -0
- package/lib/docker-compose/docker-compose.js +133 -0
- package/lib/docker-compose/index.d.ts +5 -0
- package/lib/docker-compose/index.js +18 -0
- package/lib/file.js +1 -1
- package/lib/gitattributes.js +1 -1
- package/lib/github/auto-approve.js +1 -1
- package/lib/github/auto-merge.js +1 -1
- package/lib/github/dependabot.js +1 -1
- package/lib/github/github-credentials.js +1 -1
- package/lib/github/github-project.js +1 -1
- package/lib/github/github.js +1 -1
- package/lib/github/mergify.js +1 -1
- package/lib/github/pr-template.js +1 -1
- package/lib/github/pull-request-lint.js +1 -1
- package/lib/github/stale.js +1 -1
- package/lib/github/task-workflow.js +1 -1
- package/lib/github/workflows.js +1 -1
- package/lib/gitlab/configuration.js +1 -1
- package/lib/gitlab/gitlab-configuration.js +1 -1
- package/lib/gitlab/nested-configuration.js +1 -1
- package/lib/gitpod.js +1 -1
- package/lib/ignore-file.js +1 -1
- package/lib/ini.js +1 -1
- package/lib/java/java-project.js +1 -1
- package/lib/java/junit.js +1 -1
- package/lib/java/maven-compile.js +1 -1
- package/lib/java/maven-packaging.js +1 -1
- package/lib/java/maven-sample.js +1 -1
- package/lib/java/pom.js +1 -1
- package/lib/java/projenrc.js +1 -1
- package/lib/javascript/bundler.js +1 -1
- package/lib/javascript/eslint.js +1 -1
- package/lib/javascript/jest.js +1 -1
- package/lib/javascript/node-package.js +1 -1
- package/lib/javascript/node-project.js +1 -1
- package/lib/javascript/npm-config.js +1 -1
- package/lib/javascript/prettier.js +1 -1
- package/lib/javascript/projenrc.js +1 -1
- package/lib/javascript/typescript-config.js +1 -1
- package/lib/javascript/upgrade-dependencies.js +2 -2
- package/lib/json-patch.js +1 -1
- package/lib/json.js +1 -1
- package/lib/license.js +1 -1
- package/lib/logger.js +1 -1
- package/lib/makefile.js +1 -1
- package/lib/object-file.js +1 -1
- package/lib/project-build.js +1 -1
- package/lib/project.js +1 -1
- package/lib/projects.js +1 -1
- package/lib/projenrc-json.js +1 -1
- package/lib/python/pip.js +1 -1
- package/lib/python/poetry.js +2 -2
- package/lib/python/projenrc.js +1 -1
- package/lib/python/pytest-sample.js +1 -1
- package/lib/python/pytest.js +1 -1
- package/lib/python/python-project.js +1 -1
- package/lib/python/python-sample.js +1 -1
- package/lib/python/requirements-file.js +1 -1
- package/lib/python/setuppy.js +1 -1
- package/lib/python/setuptools.js +1 -1
- package/lib/python/venv.js +1 -1
- package/lib/readme.js +1 -1
- package/lib/release/publisher.js +1 -1
- package/lib/release/release-trigger.js +1 -1
- package/lib/release/release.js +1 -1
- package/lib/renovatebot.js +1 -1
- package/lib/sample-file.js +2 -2
- package/lib/semver.js +1 -1
- package/lib/source-code.js +1 -1
- package/lib/task-runtime.js +1 -1
- package/lib/task.js +1 -1
- package/lib/tasks.js +1 -1
- package/lib/testing.js +1 -1
- package/lib/textfile.js +1 -1
- package/lib/toml.js +1 -1
- package/lib/typescript/projenrc.js +1 -1
- package/lib/typescript/typescript-typedoc.js +1 -1
- package/lib/typescript/typescript.js +3 -3
- package/lib/version.js +1 -1
- package/lib/vscode/devcontainer.js +1 -1
- package/lib/vscode/extensions.js +1 -1
- package/lib/vscode/launch-config.js +1 -1
- package/lib/vscode/settings.js +1 -1
- package/lib/vscode/vscode.js +1 -1
- package/lib/web/next.js +3 -3
- package/lib/web/postcss.js +1 -1
- package/lib/web/react.js +4 -4
- package/lib/web/tailwind.js +1 -1
- package/lib/xmlfile.js +1 -1
- package/lib/yaml.js +1 -1
- package/package.json +1 -1
- package/lib/docker-compose.d.ts +0 -308
- package/lib/docker-compose.js +0 -284
package/lib/docker-compose.d.ts
DELETED
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { Component } from "./component";
|
|
2
|
-
import { Project } from "./project";
|
|
3
|
-
/**
|
|
4
|
-
* Props for DockerCompose.
|
|
5
|
-
*/
|
|
6
|
-
export interface DockerComposeProps {
|
|
7
|
-
/**
|
|
8
|
-
* A name to add to the docker-compose.yml filename.
|
|
9
|
-
* @example 'myname' yields 'docker-compose.myname.yml'
|
|
10
|
-
* @default - no name is added
|
|
11
|
-
*/
|
|
12
|
-
readonly nameSuffix?: string;
|
|
13
|
-
/**
|
|
14
|
-
* Docker Compose schema version do be used
|
|
15
|
-
* @default 3.3
|
|
16
|
-
*/
|
|
17
|
-
readonly schemaVersion?: string;
|
|
18
|
-
/**
|
|
19
|
-
* Service descriptions.
|
|
20
|
-
*/
|
|
21
|
-
readonly services?: Record<string, DockerComposeServiceDescription>;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Options for port mappings.
|
|
25
|
-
*/
|
|
26
|
-
export interface DockerComposePortMappingOptions {
|
|
27
|
-
/**
|
|
28
|
-
* Port mapping protocol.
|
|
29
|
-
* @default DockerComposeProtocol.TCP
|
|
30
|
-
*/
|
|
31
|
-
readonly protocol?: DockerComposeProtocol;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Create a docker-compose YAML file.
|
|
35
|
-
*/
|
|
36
|
-
export declare class DockerCompose extends Component {
|
|
37
|
-
/**
|
|
38
|
-
* Depends on a service name.
|
|
39
|
-
*/
|
|
40
|
-
static serviceName(serviceName: string): IDockerComposeServiceName;
|
|
41
|
-
/**
|
|
42
|
-
* Create a port mapping.
|
|
43
|
-
* @param publishedPort Published port number
|
|
44
|
-
* @param targetPort Container's port number
|
|
45
|
-
* @param options Port mapping options
|
|
46
|
-
*/
|
|
47
|
-
static portMapping(publishedPort: number, targetPort: number, options?: DockerComposePortMappingOptions): DockerComposeServicePort;
|
|
48
|
-
/**
|
|
49
|
-
* Create a bind volume that binds a host path to the target path in the container.
|
|
50
|
-
* @param sourcePath Host path name
|
|
51
|
-
* @param targetPath Target path name
|
|
52
|
-
*/
|
|
53
|
-
static bindVolume(sourcePath: string, targetPath: string): IDockerComposeVolumeBinding;
|
|
54
|
-
/**
|
|
55
|
-
* Create a named volume and mount it to the target path. If you use this
|
|
56
|
-
* named volume in several services, the volume will be shared. In this
|
|
57
|
-
* case, the volume configuration of the first-provided options are used.
|
|
58
|
-
*
|
|
59
|
-
* @param volumeName Name of the volume
|
|
60
|
-
* @param targetPath Target path
|
|
61
|
-
* @param options volume configuration (default: docker compose defaults)
|
|
62
|
-
*/
|
|
63
|
-
static namedVolume(volumeName: string, targetPath: string, options?: DockerComposeVolumeConfig): IDockerComposeVolumeBinding;
|
|
64
|
-
private readonly services;
|
|
65
|
-
private readonly version;
|
|
66
|
-
constructor(project: Project, props?: DockerComposeProps);
|
|
67
|
-
/**
|
|
68
|
-
* Add a service to the docker-compose file.
|
|
69
|
-
* @param serviceName name of the service
|
|
70
|
-
* @param description a service description
|
|
71
|
-
*/
|
|
72
|
-
addService(serviceName: string, description: DockerComposeServiceDescription): DockerComposeService;
|
|
73
|
-
/**
|
|
74
|
-
* @internal
|
|
75
|
-
*/
|
|
76
|
-
_synthesizeDockerCompose(): object;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* An interface providing the name of a docker compose service.
|
|
80
|
-
*/
|
|
81
|
-
export interface IDockerComposeServiceName {
|
|
82
|
-
/**
|
|
83
|
-
* The name of the docker compose service.
|
|
84
|
-
*/
|
|
85
|
-
readonly serviceName: string;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Description of a docker-compose.yml service.
|
|
89
|
-
*/
|
|
90
|
-
export interface DockerComposeServiceDescription {
|
|
91
|
-
/**
|
|
92
|
-
* Use a docker image.
|
|
93
|
-
* Note: You must specify either `build` or `image` key.
|
|
94
|
-
* @see imageBuild
|
|
95
|
-
*/
|
|
96
|
-
readonly image?: string;
|
|
97
|
-
/**
|
|
98
|
-
* Build a docker image.
|
|
99
|
-
* Note: You must specify either `imageBuild` or `image` key.
|
|
100
|
-
* @see image
|
|
101
|
-
*/
|
|
102
|
-
readonly imageBuild?: DockerComposeBuild;
|
|
103
|
-
/**
|
|
104
|
-
* Provide a command to the docker container.
|
|
105
|
-
* @default - use the container's default command
|
|
106
|
-
*/
|
|
107
|
-
readonly command?: string[];
|
|
108
|
-
/**
|
|
109
|
-
* Names of other services this service depends on.
|
|
110
|
-
* @default - no dependencies
|
|
111
|
-
*/
|
|
112
|
-
readonly dependsOn?: IDockerComposeServiceName[];
|
|
113
|
-
/**
|
|
114
|
-
* Mount some volumes into the service.
|
|
115
|
-
* Use one of the following to create volumes:
|
|
116
|
-
* @see DockerCompose.bindVolume() to mount a host path
|
|
117
|
-
* @see DockerCompose.namedVolume() to create & mount a named volume
|
|
118
|
-
*/
|
|
119
|
-
readonly volumes?: IDockerComposeVolumeBinding[];
|
|
120
|
-
/**
|
|
121
|
-
* Map some ports.
|
|
122
|
-
* @default - no ports are mapped
|
|
123
|
-
*/
|
|
124
|
-
readonly ports?: DockerComposeServicePort[];
|
|
125
|
-
/**
|
|
126
|
-
* Add environment variables.
|
|
127
|
-
* @default - no environment variables are provided
|
|
128
|
-
*/
|
|
129
|
-
readonly environment?: Record<string, string>;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* A docker-compose service.
|
|
133
|
-
*/
|
|
134
|
-
export declare class DockerComposeService implements IDockerComposeServiceName {
|
|
135
|
-
/**
|
|
136
|
-
* Name of the service.
|
|
137
|
-
*/
|
|
138
|
-
readonly serviceName: string;
|
|
139
|
-
/**
|
|
140
|
-
* Docker image.
|
|
141
|
-
*/
|
|
142
|
-
readonly image?: string;
|
|
143
|
-
/**
|
|
144
|
-
* Docker image build instructions.
|
|
145
|
-
*/
|
|
146
|
-
readonly imageBuild?: DockerComposeBuild;
|
|
147
|
-
/**
|
|
148
|
-
* Command to run in the container.
|
|
149
|
-
*/
|
|
150
|
-
readonly command?: string[];
|
|
151
|
-
/**
|
|
152
|
-
* Other services that this service depends on.
|
|
153
|
-
*/
|
|
154
|
-
readonly dependsOn: IDockerComposeServiceName[];
|
|
155
|
-
/**
|
|
156
|
-
* Volumes mounted in the container.
|
|
157
|
-
*/
|
|
158
|
-
readonly volumes: IDockerComposeVolumeBinding[];
|
|
159
|
-
/**
|
|
160
|
-
* Published ports.
|
|
161
|
-
*/
|
|
162
|
-
readonly ports: DockerComposeServicePort[];
|
|
163
|
-
/**
|
|
164
|
-
* Environment variables.
|
|
165
|
-
*/
|
|
166
|
-
readonly environment: Record<string, string>;
|
|
167
|
-
constructor(serviceName: string, serviceDescription: DockerComposeServiceDescription);
|
|
168
|
-
/**
|
|
169
|
-
* Add a port mapping
|
|
170
|
-
* @param publishedPort Published port number
|
|
171
|
-
* @param targetPort Container's port number
|
|
172
|
-
* @param options Port mapping options
|
|
173
|
-
*/
|
|
174
|
-
addPort(publishedPort: number, targetPort: number, options?: DockerComposePortMappingOptions): void;
|
|
175
|
-
/**
|
|
176
|
-
* Add an environment variable
|
|
177
|
-
* @param name environment variable name
|
|
178
|
-
* @param value value of the environment variable
|
|
179
|
-
*/
|
|
180
|
-
addEnvironment(name: string, value: string): void;
|
|
181
|
-
/**
|
|
182
|
-
* Make the service depend on another service.
|
|
183
|
-
* @param serviceName
|
|
184
|
-
*/
|
|
185
|
-
addDependsOn(serviceName: IDockerComposeServiceName): void;
|
|
186
|
-
/**
|
|
187
|
-
* Add a volume to the service.
|
|
188
|
-
* @param volume
|
|
189
|
-
*/
|
|
190
|
-
addVolume(volume: IDockerComposeVolumeBinding): void;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* A service port mapping
|
|
194
|
-
*/
|
|
195
|
-
export interface DockerComposeServicePort {
|
|
196
|
-
/**
|
|
197
|
-
* Published port number
|
|
198
|
-
*/
|
|
199
|
-
readonly published: number;
|
|
200
|
-
/**
|
|
201
|
-
* Target port number
|
|
202
|
-
*/
|
|
203
|
-
readonly target: number;
|
|
204
|
-
/**
|
|
205
|
-
* Network protocol
|
|
206
|
-
*/
|
|
207
|
-
readonly protocol: DockerComposeProtocol;
|
|
208
|
-
/**
|
|
209
|
-
* Port mapping mode.
|
|
210
|
-
*/
|
|
211
|
-
readonly mode: string;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Network protocol for port mapping
|
|
215
|
-
*/
|
|
216
|
-
export declare enum DockerComposeProtocol {
|
|
217
|
-
/**
|
|
218
|
-
* TCP protocol
|
|
219
|
-
*/
|
|
220
|
-
TCP = "tcp",
|
|
221
|
-
/**
|
|
222
|
-
* UDP protocol
|
|
223
|
-
*/
|
|
224
|
-
UDP = "udp"
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Build arguments for creating a docker image.
|
|
228
|
-
*/
|
|
229
|
-
export interface DockerComposeBuild {
|
|
230
|
-
/**
|
|
231
|
-
* Docker build context directory.
|
|
232
|
-
*/
|
|
233
|
-
readonly context: string;
|
|
234
|
-
/**
|
|
235
|
-
* A dockerfile to build from.
|
|
236
|
-
* @default "Dockerfile"
|
|
237
|
-
*/
|
|
238
|
-
readonly dockerfile?: string;
|
|
239
|
-
/**
|
|
240
|
-
* Build args.
|
|
241
|
-
* @default - none are provided
|
|
242
|
-
*/
|
|
243
|
-
readonly args?: Record<string, string>;
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Volume configuration
|
|
247
|
-
*/
|
|
248
|
-
export interface DockerComposeVolumeConfig {
|
|
249
|
-
/**
|
|
250
|
-
* Driver to use for the volume
|
|
251
|
-
* @default - value is not provided
|
|
252
|
-
*/
|
|
253
|
-
readonly driver?: string;
|
|
254
|
-
/**
|
|
255
|
-
* Options to provide to the driver.
|
|
256
|
-
*/
|
|
257
|
-
readonly driverOpts?: Record<string, string>;
|
|
258
|
-
/**
|
|
259
|
-
* Set to true to indicate that the volume is externally created.
|
|
260
|
-
* @default - unset, indicating that docker-compose creates the volume
|
|
261
|
-
*/
|
|
262
|
-
readonly external?: boolean;
|
|
263
|
-
/**
|
|
264
|
-
* Name of the volume for when the volume name isn't going to work in YAML.
|
|
265
|
-
* @default - unset, indicating that docker-compose creates volumes as usual
|
|
266
|
-
*/
|
|
267
|
-
readonly name?: string;
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Volume binding information.
|
|
271
|
-
*/
|
|
272
|
-
export interface IDockerComposeVolumeBinding {
|
|
273
|
-
/**
|
|
274
|
-
* Binds the requested volume to the docker-compose volume configuration and
|
|
275
|
-
* provide mounting instructions for synthesis.
|
|
276
|
-
* @param volumeConfig the volume configuration
|
|
277
|
-
* @returns mounting instructions for the service.
|
|
278
|
-
*/
|
|
279
|
-
bind(volumeConfig: IDockerComposeVolumeConfig): DockerComposeVolumeMount;
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Storage for volume configuration.
|
|
283
|
-
*/
|
|
284
|
-
export interface IDockerComposeVolumeConfig {
|
|
285
|
-
/**
|
|
286
|
-
* Add volume configuration to the repository.
|
|
287
|
-
* @param volumeName
|
|
288
|
-
* @param configuration
|
|
289
|
-
*/
|
|
290
|
-
addVolumeConfiguration(volumeName: string, configuration: DockerComposeVolumeConfig): void;
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Service volume mounting information.
|
|
294
|
-
*/
|
|
295
|
-
export interface DockerComposeVolumeMount {
|
|
296
|
-
/**
|
|
297
|
-
* Type of volume.
|
|
298
|
-
*/
|
|
299
|
-
readonly type: string;
|
|
300
|
-
/**
|
|
301
|
-
* Volume source
|
|
302
|
-
*/
|
|
303
|
-
readonly source: string;
|
|
304
|
-
/**
|
|
305
|
-
* Volume target
|
|
306
|
-
*/
|
|
307
|
-
readonly target: string;
|
|
308
|
-
}
|
package/lib/docker-compose.js
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var _a, _b;
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.DockerComposeProtocol = exports.DockerComposeService = exports.DockerCompose = void 0;
|
|
5
|
-
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
-
const component_1 = require("./component");
|
|
7
|
-
const util_1 = require("./util");
|
|
8
|
-
const yaml_1 = require("./yaml");
|
|
9
|
-
/**
|
|
10
|
-
* Create a docker-compose YAML file.
|
|
11
|
-
*/
|
|
12
|
-
class DockerCompose extends component_1.Component {
|
|
13
|
-
constructor(project, props) {
|
|
14
|
-
super(project);
|
|
15
|
-
const nameSuffix = props?.nameSuffix ? `${props.nameSuffix}.yml` : "yml";
|
|
16
|
-
new yaml_1.YamlFile(project, `docker-compose.${nameSuffix}`, {
|
|
17
|
-
committed: true,
|
|
18
|
-
readonly: true,
|
|
19
|
-
obj: () => this._synthesizeDockerCompose(),
|
|
20
|
-
});
|
|
21
|
-
if (props?.schemaVersion && !parseFloat(props.schemaVersion)) {
|
|
22
|
-
throw Error("Version tag needs to be a number");
|
|
23
|
-
}
|
|
24
|
-
this.version = props?.schemaVersion ? props.schemaVersion : "3.3";
|
|
25
|
-
this.services = {};
|
|
26
|
-
// Add the services provided via the constructor argument.
|
|
27
|
-
const initialServices = props?.services ?? {};
|
|
28
|
-
for (const [name, serviceDescription] of Object.entries(initialServices)) {
|
|
29
|
-
this.addService(name, serviceDescription);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Depends on a service name.
|
|
34
|
-
*/
|
|
35
|
-
static serviceName(serviceName) {
|
|
36
|
-
return {
|
|
37
|
-
serviceName,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Create a port mapping.
|
|
42
|
-
* @param publishedPort Published port number
|
|
43
|
-
* @param targetPort Container's port number
|
|
44
|
-
* @param options Port mapping options
|
|
45
|
-
*/
|
|
46
|
-
static portMapping(publishedPort, targetPort, options) {
|
|
47
|
-
const protocol = options?.protocol ?? DockerComposeProtocol.TCP;
|
|
48
|
-
return {
|
|
49
|
-
target: targetPort,
|
|
50
|
-
published: publishedPort,
|
|
51
|
-
protocol: protocol,
|
|
52
|
-
mode: "host",
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Create a bind volume that binds a host path to the target path in the container.
|
|
57
|
-
* @param sourcePath Host path name
|
|
58
|
-
* @param targetPath Target path name
|
|
59
|
-
*/
|
|
60
|
-
static bindVolume(sourcePath, targetPath) {
|
|
61
|
-
return {
|
|
62
|
-
bind(_volumeInfo) {
|
|
63
|
-
return {
|
|
64
|
-
type: "bind",
|
|
65
|
-
source: sourcePath,
|
|
66
|
-
target: targetPath,
|
|
67
|
-
};
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Create a named volume and mount it to the target path. If you use this
|
|
73
|
-
* named volume in several services, the volume will be shared. In this
|
|
74
|
-
* case, the volume configuration of the first-provided options are used.
|
|
75
|
-
*
|
|
76
|
-
* @param volumeName Name of the volume
|
|
77
|
-
* @param targetPath Target path
|
|
78
|
-
* @param options volume configuration (default: docker compose defaults)
|
|
79
|
-
*/
|
|
80
|
-
static namedVolume(volumeName, targetPath, options = {}) {
|
|
81
|
-
return {
|
|
82
|
-
bind(volumeInfo) {
|
|
83
|
-
volumeInfo.addVolumeConfiguration(volumeName, options);
|
|
84
|
-
return {
|
|
85
|
-
type: "volume",
|
|
86
|
-
source: volumeName,
|
|
87
|
-
target: targetPath,
|
|
88
|
-
};
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Add a service to the docker-compose file.
|
|
94
|
-
* @param serviceName name of the service
|
|
95
|
-
* @param description a service description
|
|
96
|
-
*/
|
|
97
|
-
addService(serviceName, description) {
|
|
98
|
-
const service = new DockerComposeService(serviceName, description);
|
|
99
|
-
this.services[serviceName] = service;
|
|
100
|
-
return service;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* @internal
|
|
104
|
-
*/
|
|
105
|
-
_synthesizeDockerCompose() {
|
|
106
|
-
if (Object.keys(this.services).length === 0) {
|
|
107
|
-
throw new Error("DockerCompose requires at least one service");
|
|
108
|
-
}
|
|
109
|
-
return renderDockerComposeFile(this.services, this.version);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
exports.DockerCompose = DockerCompose;
|
|
113
|
-
_a = JSII_RTTI_SYMBOL_1;
|
|
114
|
-
DockerCompose[_a] = { fqn: "projen.DockerCompose", version: "0.67.26" };
|
|
115
|
-
/**
|
|
116
|
-
* A docker-compose service.
|
|
117
|
-
*/
|
|
118
|
-
class DockerComposeService {
|
|
119
|
-
constructor(serviceName, serviceDescription) {
|
|
120
|
-
if ((!serviceDescription.imageBuild && !serviceDescription.image) ||
|
|
121
|
-
(serviceDescription.imageBuild && serviceDescription.image)) {
|
|
122
|
-
throw new Error(`A service ${serviceName} requires exactly one of a \`imageBuild\` or \`image\` key`);
|
|
123
|
-
}
|
|
124
|
-
this.serviceName = serviceName;
|
|
125
|
-
this.command = serviceDescription.command;
|
|
126
|
-
this.image = serviceDescription.image;
|
|
127
|
-
this.imageBuild = serviceDescription.imageBuild;
|
|
128
|
-
this.dependsOn = serviceDescription.dependsOn ?? [];
|
|
129
|
-
this.volumes = serviceDescription.volumes ?? [];
|
|
130
|
-
this.ports = serviceDescription.ports ?? [];
|
|
131
|
-
this.environment = serviceDescription.environment ?? {};
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Add a port mapping
|
|
135
|
-
* @param publishedPort Published port number
|
|
136
|
-
* @param targetPort Container's port number
|
|
137
|
-
* @param options Port mapping options
|
|
138
|
-
*/
|
|
139
|
-
addPort(publishedPort, targetPort, options) {
|
|
140
|
-
this.ports?.push(DockerCompose.portMapping(publishedPort, targetPort, options));
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Add an environment variable
|
|
144
|
-
* @param name environment variable name
|
|
145
|
-
* @param value value of the environment variable
|
|
146
|
-
*/
|
|
147
|
-
addEnvironment(name, value) {
|
|
148
|
-
this.environment[name] = value;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Make the service depend on another service.
|
|
152
|
-
* @param serviceName
|
|
153
|
-
*/
|
|
154
|
-
addDependsOn(serviceName) {
|
|
155
|
-
this.dependsOn.push(serviceName);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Add a volume to the service.
|
|
159
|
-
* @param volume
|
|
160
|
-
*/
|
|
161
|
-
addVolume(volume) {
|
|
162
|
-
this.volumes.push(volume);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
exports.DockerComposeService = DockerComposeService;
|
|
166
|
-
_b = JSII_RTTI_SYMBOL_1;
|
|
167
|
-
DockerComposeService[_b] = { fqn: "projen.DockerComposeService", version: "0.67.26" };
|
|
168
|
-
/**
|
|
169
|
-
* Network protocol for port mapping
|
|
170
|
-
*/
|
|
171
|
-
var DockerComposeProtocol;
|
|
172
|
-
(function (DockerComposeProtocol) {
|
|
173
|
-
/**
|
|
174
|
-
* TCP protocol
|
|
175
|
-
*/
|
|
176
|
-
DockerComposeProtocol["TCP"] = "tcp";
|
|
177
|
-
/**
|
|
178
|
-
* UDP protocol
|
|
179
|
-
*/
|
|
180
|
-
DockerComposeProtocol["UDP"] = "udp";
|
|
181
|
-
})(DockerComposeProtocol = exports.DockerComposeProtocol || (exports.DockerComposeProtocol = {}));
|
|
182
|
-
function renderDockerComposeFile(serviceDescriptions, version) {
|
|
183
|
-
// Record volume configuration
|
|
184
|
-
const volumeConfig = {};
|
|
185
|
-
const volumeInfo = {
|
|
186
|
-
addVolumeConfiguration(volumeName, configuration) {
|
|
187
|
-
if (!volumeConfig[volumeName]) {
|
|
188
|
-
// First volume configuration takes precedence.
|
|
189
|
-
volumeConfig[volumeName] = configuration;
|
|
190
|
-
}
|
|
191
|
-
},
|
|
192
|
-
};
|
|
193
|
-
// Render service configuration
|
|
194
|
-
const services = {};
|
|
195
|
-
for (const [serviceName, serviceDescription] of Object.entries(serviceDescriptions ?? {})) {
|
|
196
|
-
// Resolve the names of each dependency and check that they exist.
|
|
197
|
-
// Note: They may not exist if the user made a mistake when referencing a
|
|
198
|
-
// service by name via `DockerCompose.serviceName()`.
|
|
199
|
-
// @see DockerCompose.serviceName
|
|
200
|
-
const dependsOn = Array();
|
|
201
|
-
for (const dependsOnServiceName of serviceDescription.dependsOn ?? []) {
|
|
202
|
-
const resolvedServiceName = dependsOnServiceName.serviceName;
|
|
203
|
-
if (resolvedServiceName === serviceName) {
|
|
204
|
-
throw new Error(`Service ${serviceName} cannot depend on itself`);
|
|
205
|
-
}
|
|
206
|
-
if (!serviceDescriptions[resolvedServiceName]) {
|
|
207
|
-
throw new Error(`Unable to resolve service named ${resolvedServiceName} for ${serviceName}`);
|
|
208
|
-
}
|
|
209
|
-
dependsOn.push(resolvedServiceName);
|
|
210
|
-
}
|
|
211
|
-
// Give each volume binding a chance to bind any necessary volume
|
|
212
|
-
// configuration and provide volume mount information for the service.
|
|
213
|
-
const volumes = [];
|
|
214
|
-
for (const volumeBinding of serviceDescription.volumes ?? []) {
|
|
215
|
-
volumes.push(volumeBinding.bind(volumeInfo));
|
|
216
|
-
}
|
|
217
|
-
// Create and store the service configuration, taking care not to create
|
|
218
|
-
// object members with undefined values.
|
|
219
|
-
services[serviceName] = {
|
|
220
|
-
...getObjectWithKeyAndValueIfValueIsDefined("image", serviceDescription.image),
|
|
221
|
-
...getObjectWithKeyAndValueIfValueIsDefined("build", serviceDescription.imageBuild),
|
|
222
|
-
...getObjectWithKeyAndValueIfValueIsDefined("command", serviceDescription.command),
|
|
223
|
-
...(Object.keys(serviceDescription.environment).length > 0
|
|
224
|
-
? { environment: serviceDescription.environment }
|
|
225
|
-
: {}),
|
|
226
|
-
...(serviceDescription.ports.length > 0
|
|
227
|
-
? { ports: serviceDescription.ports }
|
|
228
|
-
: {}),
|
|
229
|
-
...(dependsOn.length > 0 ? { dependsOn } : {}),
|
|
230
|
-
...(volumes.length > 0 ? { volumes } : {}),
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
// Explicit with the type here because the decamelize step after this wipes
|
|
234
|
-
// out types.
|
|
235
|
-
const input = {
|
|
236
|
-
version,
|
|
237
|
-
services,
|
|
238
|
-
...(Object.keys(volumeConfig).length > 0 ? { volumes: volumeConfig } : {}),
|
|
239
|
-
};
|
|
240
|
-
// Change most keys to snake case.
|
|
241
|
-
return util_1.decamelizeKeysRecursively(input, {
|
|
242
|
-
shouldDecamelize: shouldDecamelizeDockerComposeKey,
|
|
243
|
-
separator: "_",
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* Returns `{ [key]: value }` if `value` is defined, otherwise returns `{}` so
|
|
248
|
-
* that object spreading can be used to generate a peculiar interface.
|
|
249
|
-
* @param key
|
|
250
|
-
* @param value
|
|
251
|
-
*/
|
|
252
|
-
function getObjectWithKeyAndValueIfValueIsDefined(key, value) {
|
|
253
|
-
return value !== undefined ? { [key]: value } : {};
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Determines whether the key at the given path should be decamelized.
|
|
257
|
-
* Largely, all keys should be snake cased. But, there are some
|
|
258
|
-
* exceptions for user-provided names for services, volumes, and
|
|
259
|
-
* environment variables.
|
|
260
|
-
*
|
|
261
|
-
* @param path
|
|
262
|
-
*/
|
|
263
|
-
function shouldDecamelizeDockerComposeKey(path) {
|
|
264
|
-
const poundPath = path.join("#");
|
|
265
|
-
// Does not decamelize user's names.
|
|
266
|
-
// services.namehere:
|
|
267
|
-
// volumes.namehere:
|
|
268
|
-
if (/^(services|volumes)#[^#]+$/.test(poundPath)) {
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
// Does not decamelize environment variables
|
|
272
|
-
// services.namehere.environment.*
|
|
273
|
-
if (/^services#[^#]+#environment#/.test(poundPath)) {
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
// Does not decamelize build arguments
|
|
277
|
-
// services.namehere.build.args.*
|
|
278
|
-
if (/^services#[^#]+#build#args#/.test(poundPath)) {
|
|
279
|
-
return false;
|
|
280
|
-
}
|
|
281
|
-
// Otherwise, let it all decamelize.
|
|
282
|
-
return true;
|
|
283
|
-
}
|
|
284
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9ja2VyLWNvbXBvc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZG9ja2VyLWNvbXBvc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSwyQ0FBd0M7QUFFeEMsaUNBQW1EO0FBQ25ELGlDQUFrQztBQW9DbEM7O0dBRUc7QUFDSCxNQUFhLGFBQWMsU0FBUSxxQkFBUztJQWlGMUMsWUFBWSxPQUFnQixFQUFFLEtBQTBCO1FBQ3RELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVmLE1BQU0sVUFBVSxHQUFHLEtBQUssRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBTSxDQUFDLFVBQVUsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7UUFDMUUsSUFBSSxlQUFRLENBQUMsT0FBTyxFQUFFLGtCQUFrQixVQUFVLEVBQUUsRUFBRTtZQUNwRCxTQUFTLEVBQUUsSUFBSTtZQUNmLFFBQVEsRUFBRSxJQUFJO1lBQ2QsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRTtTQUMzQyxDQUFDLENBQUM7UUFFSCxJQUFJLEtBQUssRUFBRSxhQUFhLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQzVELE1BQU0sS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7U0FDakQ7UUFDRCxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUNsRSxJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUVuQiwwREFBMEQ7UUFDMUQsTUFBTSxlQUFlLEdBQUcsS0FBSyxFQUFFLFFBQVEsSUFBSSxFQUFFLENBQUM7UUFDOUMsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxl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bmVudFwiO1xuaW1wb3J0IHsgUHJvamVjdCB9IGZyb20gXCIuL3Byb2plY3RcIjtcbmltcG9ydCB7IGRlY2FtZWxpemVLZXlzUmVjdXJzaXZlbHkgfSBmcm9tIFwiLi91dGlsXCI7XG5pbXBvcnQgeyBZYW1sRmlsZSB9IGZyb20gXCIuL3lhbWxcIjtcblxuLyoqXG4gKiBQcm9wcyBmb3IgRG9ja2VyQ29tcG9zZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlUHJvcHMge1xuICAvKipcbiAgICogQSBuYW1lIHRvIGFkZCB0byB0aGUgZG9ja2VyLWNvbXBvc2UueW1sIGZpbGVuYW1lLlxuICAgKiBAZXhhbXBsZSAnbXluYW1lJyB5aWVsZHMgJ2RvY2tlci1jb21wb3NlLm15bmFtZS55bWwnXG4gICAqIEBkZWZhdWx0IC0gbm8gbmFtZSBpcyBhZGRlZFxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZVN1ZmZpeD86IHN0cmluZztcblxuICAvKipcbiAgICogRG9ja2VyIENvbXBvc2Ugc2NoZW1hIHZlcnNpb24gZG8gYmUgdXNlZFxuICAgKiBAZGVmYXVsdCAzLjNcbiAgICovXG4gIHJlYWRvbmx5IHNjaGVtYVZlcnNpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNlcnZpY2UgZGVzY3JpcHRpb25zLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VydmljZXM/OiBSZWNvcmQ8c3RyaW5nLCBEb2NrZXJDb21wb3NlU2VydmljZURlc2NyaXB0aW9uPjtcbn1cblxuLyoqXG4gKiBPcHRpb25zIGZvciBwb3J0IG1hcHBpbmdzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERvY2tlckNvbXBvc2VQb3J0TWFwcGluZ09wdGlvbnMge1xuICAvKipcbiAgICogUG9ydCBtYXBwaW5nIHByb3RvY29sLlxuICAgKiBAZGVmYXVsdCBEb2NrZXJDb21wb3NlUHJvdG9jb2wuVENQXG4gICAqL1xuICByZWFkb25seSBwcm90b2NvbD86IERvY2tlckNvbXBvc2VQcm90b2NvbDtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBkb2NrZXItY29tcG9zZSBZQU1MIGZpbGUuXG4gKi9cbmV4cG9ydCBjbGFzcyBEb2NrZXJDb21wb3NlIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgLyoqXG4gICAqIERlcGVuZHMgb24gYSBzZXJ2aWNlIG5hbWUuXG4gICAqL1xuICBzdGF0aWMgc2VydmljZU5hbWUoc2VydmljZU5hbWU6IHN0cmluZyk6IElEb2NrZXJDb21wb3NlU2VydmljZU5hbWUge1xuICAgIHJldHVybiB7XG4gICAgICBzZXJ2aWNlTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHBvcnQgbWFwcGluZy5cbiAgICogQHBhcmFtIHB1Ymxpc2hlZFBvcnQgUHVibGlzaGVkIHBvcnQgbnVtYmVyXG4gICAqIEBwYXJhbSB0YXJnZXRQb3J0IENvbnRhaW5lcidzIHBvcnQgbnVtYmVyXG4gICAqIEBwYXJhbSBvcHRpb25zIFBvcnQgbWFwcGluZyBvcHRpb25zXG4gICAqL1xuICBzdGF0aWMgcG9ydE1hcHBpbmcoXG4gICAgcHVibGlzaGVkUG9ydDogbnVtYmVyLFxuICAgIHRhcmdldFBvcnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogRG9ja2VyQ29tcG9zZVBvcnRNYXBwaW5nT3B0aW9uc1xuICApOiBEb2NrZXJDb21wb3NlU2VydmljZVBvcnQge1xuICAgIGNvbnN0IHByb3RvY29sID0gb3B0aW9ucz8ucHJvdG9jb2wgPz8gRG9ja2VyQ29tcG9zZVByb3RvY29sLlRDUDtcblxuICAgIHJldHVybiB7XG4gICAgICB0YXJnZXQ6IHRhcmdldFBvcnQsXG4gICAgICBwdWJsaXNoZWQ6IHB1Ymxpc2hlZFBvcnQsXG4gICAgICBwcm90b2NvbDogcHJvdG9jb2wsXG4gICAgICBtb2RlOiBcImhvc3RcIixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIGJpbmQgdm9sdW1lIHRoYXQgYmluZHMgYSBob3N0IHBhdGggdG8gdGhlIHRhcmdldCBwYXRoIGluIHRoZSBjb250YWluZXIuXG4gICAqIEBwYXJhbSBzb3VyY2VQYXRoIEhvc3QgcGF0aCBuYW1lXG4gICAqIEBwYXJhbSB0YXJnZXRQYXRoIFRhcmdldCBwYXRoIG5hbWVcbiAgICovXG4gIHN0YXRpYyBiaW5kVm9sdW1lKFxuICAgIHNvdXJjZVBhdGg6IHN0cmluZyxcbiAgICB0YXJnZXRQYXRoOiBzdHJpbmdcbiAgKTogSURvY2tlckNvbXBvc2VWb2x1bWVCaW5kaW5nIHtcbiAgICByZXR1cm4ge1xuICAgICAgYmluZChfdm9sdW1lSW5mbzogSURvY2tlckNvbXBvc2VWb2x1bWVDb25maWcpOiBEb2NrZXJDb21wb3NlVm9sdW1lTW91bnQge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwiYmluZFwiLFxuICAgICAgICAgIHNvdXJjZTogc291cmNlUGF0aCxcbiAgICAgICAgICB0YXJnZXQ6IHRhcmdldFBhdGgsXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmFtZWQgdm9sdW1lIGFuZCBtb3VudCBpdCB0byB0aGUgdGFyZ2V0IHBhdGguIElmIHlvdSB1c2UgdGhpc1xuICAgKiBuYW1lZCB2b2x1bWUgaW4gc2V2ZXJhbCBzZXJ2aWNlcywgdGhlIHZvbHVtZSB3aWxsIGJlIHNoYXJlZC4gSW4gdGhpc1xuICAgKiBjYXNlLCB0aGUgdm9sdW1lIGNvbmZpZ3VyYXRpb24gb2YgdGhlIGZpcnN0LXByb3ZpZGVkIG9wdGlvbnMgYXJlIHVzZWQuXG4gICAqXG4gICAqIEBwYXJhbSB2b2x1bWVOYW1lIE5hbWUgb2YgdGhlIHZvbHVtZVxuICAgKiBAcGFyYW0gdGFyZ2V0UGF0aCBUYXJnZXQgcGF0aFxuICAgKiBAcGFyYW0gb3B0aW9ucyB2b2x1bWUgY29uZmlndXJhdGlvbiAoZGVmYXVsdDogZG9ja2VyIGNvbXBvc2UgZGVmYXVsdHMpXG4gICAqL1xuICBzdGF0aWMgbmFtZWRWb2x1bWUoXG4gICAgdm9sdW1lTmFtZTogc3RyaW5nLFxuICAgIHRhcmdldFBhdGg6IHN0cmluZyxcbiAgICBvcHRpb25zOiBEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnID0ge31cbiAgKTogSURvY2tlckNvbXBvc2VWb2x1bWVCaW5kaW5nIHtcbiAgICByZXR1cm4ge1xuICAgICAgYmluZCh2b2x1bWVJbmZvOiBJRG9ja2VyQ29tcG9zZVZvbHVtZUNvbmZpZyk6IERvY2tlckNvbXBvc2VWb2x1bWVNb3VudCB7XG4gICAgICAgIHZvbHVtZUluZm8uYWRkVm9sdW1lQ29uZmlndXJhdGlvbih2b2x1bWVOYW1lLCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwidm9sdW1lXCIsXG4gICAgICAgICAgc291cmNlOiB2b2x1bWVOYW1lLFxuICAgICAgICAgIHRhcmdldDogdGFyZ2V0UGF0aCxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgc2VydmljZXM6IFJlY29yZDxzdHJpbmcsIERvY2tlckNvbXBvc2VTZXJ2aWNlPjtcbiAgcHJpdmF0ZSByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCwgcHJvcHM/OiBEb2NrZXJDb21wb3NlUHJvcHMpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIGNvbnN0IG5hbWVTdWZmaXggPSBwcm9wcz8ubmFtZVN1ZmZpeCA/IGAke3Byb3BzIS5uYW1lU3VmZml4fS55bWxgIDogXCJ5bWxcIjtcbiAgICBuZXcgWWFtbEZpbGUocHJvamVjdCwgYGRvY2tlci1jb21wb3NlLiR7bmFtZVN1ZmZpeH1gLCB7XG4gICAgICBjb21taXR0ZWQ6IHRydWUsXG4gICAgICByZWFkb25seTogdHJ1ZSxcbiAgICAgIG9iajogKCkgPT4gdGhpcy5fc3ludGhlc2l6ZURvY2tlckNvbXBvc2UoKSxcbiAgICB9KTtcblxuICAgIGlmIChwcm9wcz8uc2NoZW1hVmVyc2lvbiAmJiAhcGFyc2VGbG9hdChwcm9wcy5zY2hlbWFWZXJzaW9uKSkge1xuICAgICAgdGhyb3cgRXJyb3IoXCJWZXJzaW9uIHRhZyBuZWVkcyB0byBiZSBhIG51bWJlclwiKTtcbiAgICB9XG4gICAgdGhpcy52ZXJzaW9uID0gcHJvcHM/LnNjaGVtYVZlcnNpb24gPyBwcm9wcy5zY2hlbWFWZXJzaW9uIDogXCIzLjNcIjtcbiAgICB0aGlzLnNlcnZpY2VzID0ge307XG5cbiAgICAvLyBBZGQgdGhlIHNlcnZpY2VzIHByb3ZpZGVkIHZpYSB0aGUgY29uc3RydWN0b3IgYXJndW1lbnQuXG4gICAgY29uc3QgaW5pdGlhbFNlcnZpY2VzID0gcHJvcHM/LnNlcnZpY2VzID8/IHt9O1xuICAgIGZvciAoY29uc3QgW25hbWUsIHNlcnZpY2VEZXNjcmlwdGlvbl0gb2YgT2JqZWN0LmVudHJpZXMoaW5pdGlhbFNlcnZpY2VzKSkge1xuICAgICAgdGhpcy5hZGRTZXJ2aWNlKG5hbWUsIHNlcnZpY2VEZXNjcmlwdGlvbik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIHNlcnZpY2UgdG8gdGhlIGRvY2tlci1jb21wb3NlIGZpbGUuXG4gICAqIEBwYXJhbSBzZXJ2aWNlTmFtZSBuYW1lIG9mIHRoZSBzZXJ2aWNlXG4gICAqIEBwYXJhbSBkZXNjcmlwdGlvbiBhIHNlcnZpY2UgZGVzY3JpcHRpb25cbiAgICovXG4gIHB1YmxpYyBhZGRTZXJ2aWNlKFxuICAgIHNlcnZpY2VOYW1lOiBzdHJpbmcsXG4gICAgZGVzY3JpcHRpb246IERvY2tlckNvbXBvc2VTZXJ2aWNlRGVzY3JpcHRpb25cbiAgKTogRG9ja2VyQ29tcG9zZVNlcnZpY2Uge1xuICAgIGNvbnN0IHNlcnZpY2UgPSBuZXcgRG9ja2VyQ29tcG9zZVNlcnZpY2Uoc2VydmljZU5hbWUsIGRlc2NyaXB0aW9uKTtcbiAgICB0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXSA9IHNlcnZpY2U7XG4gICAgcmV0dXJuIHNlcnZpY2U7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBfc3ludGhlc2l6ZURvY2tlckNvbXBvc2UoKTogb2JqZWN0IHtcbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5zZXJ2aWNlcykubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJEb2NrZXJDb21wb3NlIHJlcXVpcmVzIGF0IGxlYXN0IG9uZSBzZXJ2aWNlXCIpO1xuICAgIH1cblxuICAgIHJldHVybiByZW5kZXJEb2NrZXJDb21wb3NlRmlsZSh0aGlzLnNlcnZpY2VzLCB0aGlzLnZlcnNpb24pO1xuICB9XG59XG5cbi8qKlxuICogQW4gaW50ZXJmYWNlIHByb3ZpZGluZyB0aGUgbmFtZSBvZiBhIGRvY2tlciBjb21wb3NlIHNlcnZpY2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSURvY2tlckNvbXBvc2VTZXJ2aWNlTmFtZSB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgZG9ja2VyIGNvbXBvc2Ugc2VydmljZS5cbiAgICovXG4gIHJlYWRvbmx5IHNlcnZpY2VOYW1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGVzY3JpcHRpb24gb2YgYSBkb2NrZXItY29tcG9zZS55bWwgc2VydmljZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlU2VydmljZURlc2NyaXB0aW9uIHtcbiAgLyoqXG4gICAqIFVzZSBhIGRvY2tlciBpbWFnZS5cbiAgICogTm90ZTogWW91IG11c3Qgc3BlY2lmeSBlaXRoZXIgYGJ1aWxkYCBvciBgaW1hZ2VgIGtleS5cbiAgICogQHNlZSBpbWFnZUJ1aWxkXG4gICAqL1xuICByZWFkb25seSBpbWFnZT86IHN0cmluZztcblxuICAvKipcbiAgICogQnVpbGQgYSBkb2NrZXIgaW1hZ2UuXG4gICAqIE5vdGU6IFlvdSBtdXN0IHNwZWNpZnkgZWl0aGVyIGBpbWFnZUJ1aWxkYCBvciBgaW1hZ2VgIGtleS5cbiAgICogQHNlZSBpbWFnZVxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2VCdWlsZD86IERvY2tlckNvbXBvc2VCdWlsZDtcblxuICAvKipcbiAgICogUHJvdmlkZSBhIGNvbW1hbmQgdG8gdGhlIGRvY2tlciBjb250YWluZXIuXG4gICAqIEBkZWZhdWx0IC0gdXNlIHRoZSBjb250YWluZXIncyBkZWZhdWx0IGNvbW1hbmRcbiAgICovXG4gIHJlYWRvbmx5IGNvbW1hbmQ/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTmFtZXMgb2Ygb3RoZXIgc2VydmljZXMgdGhpcyBzZXJ2aWNlIGRlcGVuZHMgb24uXG4gICAqIEBkZWZhdWx0IC0gbm8gZGVwZW5kZW5jaWVzXG4gICAqL1xuICByZWFkb25seSBkZXBlbmRzT24/OiBJRG9ja2VyQ29tcG9zZVNlcnZpY2VOYW1lW107XG5cbiAgLyoqXG4gICAqIE1vdW50IHNvbWUgdm9sdW1lcyBpbnRvIHRoZSBzZXJ2aWNlLlxuICAgKiBVc2Ugb25lIG9mIHRoZSBmb2xsb3dpbmcgdG8gY3JlYXRlIHZvbHVtZXM6XG4gICAqIEBzZWUgRG9ja2VyQ29tcG9zZS5iaW5kVm9sdW1lKCkgdG8gbW91bnQgYSBob3N0IHBhdGhcbiAgICogQHNlZSBEb2NrZXJDb21wb3NlLm5hbWVkVm9sdW1lKCkgdG8gY3JlYXRlICYgbW91bnQgYSBuYW1lZCB2b2x1bWVcbiAgICovXG4gIHJlYWRvbmx5IHZvbHVtZXM/OiBJRG9ja2VyQ29tcG9zZVZvbHVtZUJpbmRpbmdbXTtcblxuICAvKipcbiAgICogTWFwIHNvbWUgcG9ydHMuXG4gICAqIEBkZWZhdWx0IC0gbm8gcG9ydHMgYXJlIG1hcHBlZFxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydHM/OiBEb2NrZXJDb21wb3NlU2VydmljZVBvcnRbXTtcblxuICAvKipcbiAgICogQWRkIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICogQGRlZmF1bHQgLSBubyBlbnZpcm9ubWVudCB2YXJpYWJsZXMgYXJlIHByb3ZpZGVkXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudD86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59XG5cbi8qKlxuICogQSBkb2NrZXItY29tcG9zZSBzZXJ2aWNlLlxuICovXG5leHBvcnQgY2xhc3MgRG9ja2VyQ29tcG9zZVNlcnZpY2UgaW1wbGVtZW50cyBJRG9ja2VyQ29tcG9zZVNlcnZpY2VOYW1lIHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIHNlcnZpY2UuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc2VydmljZU5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogRG9ja2VyIGltYWdlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGltYWdlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEb2NrZXIgaW1hZ2UgYnVpbGQgaW5zdHJ1Y3Rpb25zLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGltYWdlQnVpbGQ/OiBEb2NrZXJDb21wb3NlQnVpbGQ7XG5cbiAgLyoqXG4gICAqIENvbW1hbmQgdG8gcnVuIGluIHRoZSBjb250YWluZXIuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY29tbWFuZD86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBPdGhlciBzZXJ2aWNlcyB0aGF0IHRoaXMgc2VydmljZSBkZXBlbmRzIG9uLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRlcGVuZHNPbjogSURvY2tlckNvbXBvc2VTZXJ2aWNlTmFtZVtdO1xuXG4gIC8qKlxuICAgKiBWb2x1bWVzIG1vdW50ZWQgaW4gdGhlIGNvbnRhaW5lci5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB2b2x1bWVzOiBJRG9ja2VyQ29tcG9zZVZvbHVtZUJpbmRpbmdbXTtcblxuICAvKipcbiAgICogUHVibGlzaGVkIHBvcnRzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBvcnRzOiBEb2NrZXJDb21wb3NlU2VydmljZVBvcnRbXTtcblxuICAvKipcbiAgICogRW52aXJvbm1lbnQgdmFyaWFibGVzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGVudmlyb25tZW50OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNlcnZpY2VOYW1lOiBzdHJpbmcsXG4gICAgc2VydmljZURlc2NyaXB0aW9uOiBEb2NrZXJDb21wb3NlU2VydmljZURlc2NyaXB0aW9uXG4gICkge1xuICAgIGlmIChcbiAgICAgICghc2VydmljZURlc2NyaXB0aW9uLmltYWdlQnVpbGQgJiYgIXNlcnZpY2VEZXNjcmlwdGlvbi5pbWFnZSkgfHxcbiAgICAgIChzZXJ2aWNlRGVzY3JpcHRpb24uaW1hZ2VCdWlsZCAmJiBzZXJ2aWNlRGVzY3JpcHRpb24uaW1hZ2UpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBBIHNlcnZpY2UgJHtzZXJ2aWNlTmFtZX0gcmVxdWlyZXMgZXhhY3RseSBvbmUgb2YgYSBcXGBpbWFnZUJ1aWxkXFxgIG9yIFxcYGltYWdlXFxgIGtleWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXJ2aWNlTmFtZSA9IHNlcnZpY2VOYW1lO1xuICAgIHRoaXMuY29tbWFuZCA9IHNlcnZpY2VEZXNjcmlwdGlvbi5jb21tYW5kO1xuICAgIHRoaXMuaW1hZ2UgPSBzZXJ2aWNlRGVzY3JpcHRpb24uaW1hZ2U7XG4gICAgdGhpcy5pbWFnZUJ1aWxkID0gc2VydmljZURlc2NyaXB0aW9uLmltYWdlQnVpbGQ7XG4gICAgdGhpcy5kZXBlbmRzT24gPSBzZXJ2aWNlRGVzY3JpcHRpb24uZGVwZW5kc09uID8/IFtdO1xuICAgIHRoaXMudm9sdW1lcyA9IHNlcnZpY2VEZXNjcmlwdGlvbi52b2x1bWVzID8/IFtdO1xuICAgIHRoaXMucG9ydHMgPSBzZXJ2aWNlRGVzY3JpcHRpb24ucG9ydHMgPz8gW107XG4gICAgdGhpcy5lbnZpcm9ubWVudCA9IHNlcnZpY2VEZXNjcmlwdGlvbi5lbnZpcm9ubWVudCA/PyB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBwb3J0IG1hcHBpbmdcbiAgICogQHBhcmFtIHB1Ymxpc2hlZFBvcnQgUHVibGlzaGVkIHBvcnQgbnVtYmVyXG4gICAqIEBwYXJhbSB0YXJnZXRQb3J0IENvbnRhaW5lcidzIHBvcnQgbnVtYmVyXG4gICAqIEBwYXJhbSBvcHRpb25zIFBvcnQgbWFwcGluZyBvcHRpb25zXG4gICAqL1xuICBwdWJsaWMgYWRkUG9ydChcbiAgICBwdWJsaXNoZWRQb3J0OiBudW1iZXIsXG4gICAgdGFyZ2V0UG9ydDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiBEb2NrZXJDb21wb3NlUG9ydE1hcHBpbmdPcHRpb25zXG4gICkge1xuICAgIHRoaXMucG9ydHM/LnB1c2goXG4gICAgICBEb2NrZXJDb21wb3NlLnBvcnRNYXBwaW5nKHB1Ymxpc2hlZFBvcnQsIHRhcmdldFBvcnQsIG9wdGlvbnMpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYW4gZW52aXJvbm1lbnQgdmFyaWFibGVcbiAgICogQHBhcmFtIG5hbWUgZW52aXJvbm1lbnQgdmFyaWFibGUgbmFtZVxuICAgKiBAcGFyYW0gdmFsdWUgdmFsdWUgb2YgdGhlIGVudmlyb25tZW50IHZhcmlhYmxlXG4gICAqL1xuICBwdWJsaWMgYWRkRW52aXJvbm1lbnQobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5lbnZpcm9ubWVudFtuYW1lXSA9IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgdGhlIHNlcnZpY2UgZGVwZW5kIG9uIGFub3RoZXIgc2VydmljZS5cbiAgICogQHBhcmFtIHNlcnZpY2VOYW1lXG4gICAqL1xuICBwdWJsaWMgYWRkRGVwZW5kc09uKHNlcnZpY2VOYW1lOiBJRG9ja2VyQ29tcG9zZVNlcnZpY2VOYW1lKSB7XG4gICAgdGhpcy5kZXBlbmRzT24ucHVzaChzZXJ2aWNlTmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgdm9sdW1lIHRvIHRoZSBzZXJ2aWNlLlxuICAgKiBAcGFyYW0gdm9sdW1lXG4gICAqL1xuICBwdWJsaWMgYWRkVm9sdW1lKHZvbHVtZTogSURvY2tlckNvbXBvc2VWb2x1bWVCaW5kaW5nKSB7XG4gICAgdGhpcy52b2x1bWVzLnB1c2godm9sdW1lKTtcbiAgfVxufVxuXG4vKipcbiAqIEEgc2VydmljZSBwb3J0IG1hcHBpbmdcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlU2VydmljZVBvcnQge1xuICAvKipcbiAgICogUHVibGlzaGVkIHBvcnQgbnVtYmVyXG4gICAqL1xuICByZWFkb25seSBwdWJsaXNoZWQ6IG51bWJlcjtcblxuICAvKipcbiAgICogVGFyZ2V0IHBvcnQgbnVtYmVyXG4gICAqL1xuICByZWFkb25seSB0YXJnZXQ6IG51bWJlcjtcblxuICAvKipcbiAgICogTmV0d29yayBwcm90b2NvbFxuICAgKi9cbiAgcmVhZG9ubHkgcHJvdG9jb2w6IERvY2tlckNvbXBvc2VQcm90b2NvbDtcblxuICAvKipcbiAgICogUG9ydCBtYXBwaW5nIG1vZGUuXG4gICAqL1xuICByZWFkb25seSBtb2RlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogTmV0d29yayBwcm90b2NvbCBmb3IgcG9ydCBtYXBwaW5nXG4gKi9cbmV4cG9ydCBlbnVtIERvY2tlckNvbXBvc2VQcm90b2NvbCB7XG4gIC8qKlxuICAgKiBUQ1AgcHJvdG9jb2xcbiAgICovXG4gIFRDUCA9IFwidGNwXCIsXG5cbiAgLyoqXG4gICAqIFVEUCBwcm90b2NvbFxuICAgKi9cbiAgVURQID0gXCJ1ZHBcIixcbn1cblxuLyoqXG4gKiBCdWlsZCBhcmd1bWVudHMgZm9yIGNyZWF0aW5nIGEgZG9ja2VyIGltYWdlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERvY2tlckNvbXBvc2VCdWlsZCB7XG4gIC8qKlxuICAgKiBEb2NrZXIgYnVpbGQgY29udGV4dCBkaXJlY3RvcnkuXG4gICAqL1xuICByZWFkb25seSBjb250ZXh0OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgZG9ja2VyZmlsZSB0byBidWlsZCBmcm9tLlxuICAgKiBAZGVmYXVsdCBcIkRvY2tlcmZpbGVcIlxuICAgKi9cbiAgcmVhZG9ubHkgZG9ja2VyZmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogQnVpbGQgYXJncy5cbiAgICogQGRlZmF1bHQgLSBub25lIGFyZSBwcm92aWRlZFxuICAgKi9cbiAgcmVhZG9ubHkgYXJncz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59XG5cbi8qKlxuICogVm9sdW1lIGNvbmZpZ3VyYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnIHtcbiAgLyoqXG4gICAqIERyaXZlciB0byB1c2UgZm9yIHRoZSB2b2x1bWVcbiAgICogQGRlZmF1bHQgLSB2YWx1ZSBpcyBub3QgcHJvdmlkZWRcbiAgICovXG4gIHJlYWRvbmx5IGRyaXZlcj86IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9ucyB0byBwcm92aWRlIHRvIHRoZSBkcml2ZXIuXG4gICAqL1xuICByZWFkb25seSBkcml2ZXJPcHRzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblxuICAvKipcbiAgICogU2V0IHRvIHRydWUgdG8gaW5kaWNhdGUgdGhhdCB0aGUgdm9sdW1lIGlzIGV4dGVybmFsbHkgY3JlYXRlZC5cbiAgICogQGRlZmF1bHQgLSB1bnNldCwgaW5kaWNhdGluZyB0aGF0IGRvY2tlci1jb21wb3NlIGNyZWF0ZXMgdGhlIHZvbHVtZVxuICAgKi9cbiAgcmVhZG9ubHkgZXh0ZXJuYWw/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSB2b2x1bWUgZm9yIHdoZW4gdGhlIHZvbHVtZSBuYW1lIGlzbid0IGdvaW5nIHRvIHdvcmsgaW4gWUFNTC5cbiAgICogQGRlZmF1bHQgLSB1bnNldCwgaW5kaWNhdGluZyB0aGF0IGRvY2tlci1jb21wb3NlIGNyZWF0ZXMgdm9sdW1lcyBhcyB1c3VhbFxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBWb2x1bWUgYmluZGluZyBpbmZvcm1hdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJRG9ja2VyQ29tcG9zZVZvbHVtZUJpbmRpbmcge1xuICAvKipcbiAgICogQmluZHMgdGhlIHJlcXVlc3RlZCB2b2x1bWUgdG8gdGhlIGRvY2tlci1jb21wb3NlIHZvbHVtZSBjb25maWd1cmF0aW9uIGFuZFxuICAgKiBwcm92aWRlIG1vdW50aW5nIGluc3RydWN0aW9ucyBmb3Igc3ludGhlc2lzLlxuICAgKiBAcGFyYW0gdm9sdW1lQ29uZmlnIHRoZSB2b2x1bWUgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJucyBtb3VudGluZyBpbnN0cnVjdGlvbnMgZm9yIHRoZSBzZXJ2aWNlLlxuICAgKi9cbiAgYmluZCh2b2x1bWVDb25maWc6IElEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnKTogRG9ja2VyQ29tcG9zZVZvbHVtZU1vdW50O1xufVxuXG4vKipcbiAqIFN0b3JhZ2UgZm9yIHZvbHVtZSBjb25maWd1cmF0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnIHtcbiAgLyoqXG4gICAqIEFkZCB2b2x1bWUgY29uZmlndXJhdGlvbiB0byB0aGUgcmVwb3NpdG9yeS5cbiAgICogQHBhcmFtIHZvbHVtZU5hbWVcbiAgICogQHBhcmFtIGNvbmZpZ3VyYXRpb25cbiAgICovXG4gIGFkZFZvbHVtZUNvbmZpZ3VyYXRpb24oXG4gICAgdm9sdW1lTmFtZTogc3RyaW5nLFxuICAgIGNvbmZpZ3VyYXRpb246IERvY2tlckNvbXBvc2VWb2x1bWVDb25maWdcbiAgKTogdm9pZDtcbn1cblxuLyoqXG4gKiBTZXJ2aWNlIHZvbHVtZSBtb3VudGluZyBpbmZvcm1hdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb2NrZXJDb21wb3NlVm9sdW1lTW91bnQge1xuICAvKipcbiAgICogVHlwZSBvZiB2b2x1bWUuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFZvbHVtZSBzb3VyY2VcbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBWb2x1bWUgdGFyZ2V0XG4gICAqL1xuICByZWFkb25seSB0YXJnZXQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBTdHJ1Y3R1cmUgb2YgYSBkb2NrZXIgY29tcG9zZSBmaWxlIGJlZm9yZSB3ZSBkZWNhbWVsaXplLlxuICogQGludGVybmFsXG4gKi9cbmludGVyZmFjZSBEb2NrZXJDb21wb3NlRmlsZVNjaGVtYSB7XG4gIHZlcnNpb246IHN0cmluZztcbiAgc2VydmljZXM6IFJlY29yZDxzdHJpbmcsIERvY2tlckNvbXBvc2VGaWxlU2VydmljZVNjaGVtYT47XG4gIHZvbHVtZXM/OiBSZWNvcmQ8c3RyaW5nLCBEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnPjtcbn1cblxuLyoqXG4gKiBTdHJ1Y3R1cmUgb2YgYSBkb2NrZXIgY29tcG9zZSBmaWxlJ3Mgc2VydmljZSBiZWZvcmUgd2UgZGVjYW1lbGl6ZS5cbiAqIEBpbnRlcm5hbFxuICovXG5pbnRlcmZhY2UgRG9ja2VyQ29tcG9zZUZpbGVTZXJ2aWNlU2NoZW1hIHtcbiAgcmVhZG9ubHkgZGVwZW5kc09uPzogc3RyaW5nW107XG4gIHJlYWRvbmx5IGJ1aWxkPzogRG9ja2VyQ29tcG9zZUJ1aWxkO1xuICByZWFkb25seSBpbWFnZT86IHN0cmluZztcbiAgcmVhZG9ubHkgY29tbWFuZD86IHN0cmluZ1tdO1xuICByZWFkb25seSB2b2x1bWVzPzogRG9ja2VyQ29tcG9zZVZvbHVtZU1vdW50W107XG4gIHJlYWRvbmx5IHBvcnRzPzogRG9ja2VyQ29tcG9zZVNlcnZpY2VQb3J0W107XG4gIHJlYWRvbmx5IGVudmlyb25tZW50PzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn1cblxuZnVuY3Rpb24gcmVuZGVyRG9ja2VyQ29tcG9zZUZpbGUoXG4gIHNlcnZpY2VEZXNjcmlwdGlvbnM6IFJlY29yZDxzdHJpbmcsIERvY2tlckNvbXBvc2VTZXJ2aWNlPixcbiAgdmVyc2lvbjogc3RyaW5nXG4pOiBvYmplY3Qge1xuICAvLyBSZWNvcmQgdm9sdW1lIGNvbmZpZ3VyYXRpb25cbiAgY29uc3Qgdm9sdW1lQ29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBEb2NrZXJDb21wb3NlVm9sdW1lQ29uZmlnPiA9IHt9O1xuICBjb25zdCB2b2x1bWVJbmZvOiBJRG9ja2VyQ29tcG9zZVZvbHVtZUNvbmZpZyA9IHtcbiAgICBhZGRWb2x1bWVDb25maWd1cmF0aW9uKFxuICAgICAgdm9sdW1lTmFtZTogc3RyaW5nLFxuICAgICAgY29uZmlndXJhdGlvbjogRG9ja2VyQ29tcG9zZVZvbHVtZUNvbmZpZ1xuICAgICkge1xuICAgICAgaWYgKCF2b2x1bWVDb25maWdbdm9sdW1lTmFtZV0pIHtcbiAgICAgICAgLy8gRmlyc3Qgdm9sdW1lIGNvbmZpZ3VyYXRpb24gdGFrZXMgcHJlY2VkZW5jZS5cbiAgICAgICAgdm9sdW1lQ29uZmlnW3ZvbHVtZU5hbWVdID0gY29uZmlndXJhdGlvbjtcbiAgICAgIH1cbiAgICB9LFxuICB9O1xuXG4gIC8vIFJlbmRlciBzZXJ2aWNlIGNvbmZpZ3VyYXRpb25cbiAgY29uc3Qgc2VydmljZXM6IFJlY29yZDxzdHJpbmcsIERvY2tlckNvbXBvc2VGaWxlU2VydmljZVNjaGVtYT4gPSB7fTtcbiAgZm9yIChjb25zdCBbc2VydmljZU5hbWUsIHNlcnZpY2VEZXNjcmlwdGlvbl0gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgc2VydmljZURlc2NyaXB0aW9ucyA/PyB7fVxuICApKSB7XG4gICAgLy8gUmVzb2x2ZSB0aGUgbmFtZXMgb2YgZWFjaCBkZXBlbmRlbmN5IGFuZCBjaGVjayB0aGF0IHRoZXkgZXhpc3QuXG4gICAgLy8gTm90ZTogVGhleSBtYXkgbm90IGV4aXN0IGlmIHRoZSB1c2VyIG1hZGUgYSBtaXN0YWtlIHdoZW4gcmVmZXJlbmNpbmcgYVxuICAgIC8vIHNlcnZpY2UgYnkgbmFtZSB2aWEgYERvY2tlckNvbXBvc2Uuc2VydmljZU5hbWUoKWAuXG4gICAgLy8gQHNlZSBEb2NrZXJDb21wb3NlLnNlcnZpY2VOYW1lXG4gICAgY29uc3QgZGVwZW5kc09uID0gQXJyYXk8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3QgZGVwZW5kc09uU2VydmljZU5hbWUgb2Ygc2VydmljZURlc2NyaXB0aW9uLmRlcGVuZHNPbiA/PyBbXSkge1xuICAgICAgY29uc3QgcmVzb2x2ZWRTZXJ2aWNlTmFtZSA9IGRlcGVuZHNPblNlcnZpY2VOYW1lLnNlcnZpY2VOYW1lO1xuICAgICAgaWYgKHJlc29sdmVkU2VydmljZU5hbWUgPT09IHNlcnZpY2VOYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgU2VydmljZSAke3NlcnZpY2VOYW1lfSBjYW5ub3QgZGVwZW5kIG9uIGl0c2VsZmApO1xuICAgICAgfVxuICAgICAgaWYgKCFzZXJ2aWNlRGVzY3JpcHRpb25zW3Jlc29sdmVkU2VydmljZU5hbWVdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVW5hYmxlIHRvIHJlc29sdmUgc2VydmljZSBuYW1lZCAke3Jlc29sdmVkU2VydmljZU5hbWV9IGZvciAke3NlcnZpY2VOYW1lfWBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgZGVwZW5kc09uLnB1c2gocmVzb2x2ZWRTZXJ2aWNlTmFtZSk7XG4gICAgfVxuXG4gICAgLy8gR2l2ZSBlYWNoIHZvbHVtZSBiaW5kaW5nIGEgY2hhbmNlIHRvIGJpbmQgYW55IG5lY2Vzc2FyeSB2b2x1bWVcbiAgICAvLyBjb25maWd1cmF0aW9uIGFuZCBwcm92aWRlIHZvbHVtZSBtb3VudCBpbmZvcm1hdGlvbiBmb3IgdGhlIHNlcnZpY2UuXG4gICAgY29uc3Qgdm9sdW1lczogRG9ja2VyQ29tcG9zZVZvbHVtZU1vdW50W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHZvbHVtZUJpbmRpbmcgb2Ygc2VydmljZURlc2NyaXB0aW9uLnZvbHVtZXMgPz8gW10pIHtcbiAgICAgIHZvbHVtZXMucHVzaCh2b2x1bWVCaW5kaW5nLmJpbmQodm9sdW1lSW5mbykpO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBhbmQgc3RvcmUgdGhlIHNlcnZpY2UgY29uZmlndXJhdGlvbiwgdGFraW5nIGNhcmUgbm90IHRvIGNyZWF0ZVxuICAgIC8vIG9iamVjdCBtZW1iZXJzIHdpdGggdW5kZWZpbmVkIHZhbHVlcy5cbiAgICBzZXJ2aWNlc1tzZXJ2aWNlTmFtZV0gPSB7XG4gICAgICAuLi5nZXRPYmplY3RXaXRoS2V5QW5kVmFsdWVJZlZhbHVlSXNEZWZpbmVkKFxuICAgICAgICBcImltYWdlXCIsXG4gICAgICAgIHNlcnZpY2VEZXNjcmlwdGlvbi5pbWFnZVxuICAgICAgKSxcbiAgICAgIC4uLmdldE9iamVjdFdpdGhLZXlBbmRWYWx1ZUlmVmFsdWVJc0RlZmluZWQoXG4gICAgICAgIFwiYnVpbGRcIixcbiAgICAgICAgc2VydmljZURlc2NyaXB0aW9uLmltYWdlQnVpbGRcbiAgICAgICksXG4gICAgICAuLi5nZXRPYmplY3RXaXRoS2V5QW5kVmFsdWVJZlZhbHVlSXNEZWZpbmVkKFxuICAgICAgICBcImNvbW1hbmRcIixcbiAgICAgICAgc2VydmljZURlc2NyaXB0aW9uLmNvbW1hbmRcbiAgICAgICksXG4gICAgICAuLi4oT2JqZWN0LmtleXMoc2VydmljZURlc2NyaXB0aW9uLmVudmlyb25tZW50KS5sZW5ndGggPiAwXG4gICAgICAgID8geyBlbnZpcm9ubWVudDogc2VydmljZURlc2NyaXB0aW9uLmVudmlyb25tZW50IH1cbiAgICAgICAgOiB7fSksXG4gICAgICAuLi4oc2VydmljZURlc2NyaXB0aW9uLnBvcnRzLmxlbmd0aCA+IDBcbiAgICAgICAgPyB7IHBvcnRzOiBzZXJ2aWNlRGVzY3JpcHRpb24ucG9ydHMgfVxuICAgICAgICA6IHt9KSxcbiAgICAgIC4uLihkZXBlbmRzT24ubGVuZ3RoID4gMCA/IHsgZGVwZW5kc09uIH0gOiB7fSksXG4gICAgICAuLi4odm9sdW1lcy5sZW5ndGggPiAwID8geyB2b2x1bWVzIH0gOiB7fSksXG4gICAgfTtcbiAgfVxuXG4gIC8vIEV4cGxpY2l0IHdpdGggdGhlIHR5cGUgaGVyZSBiZWNhdXNlIHRoZSBkZWNhbWVsaXplIHN0ZXAgYWZ0ZXIgdGhpcyB3aXBlc1xuICAvLyBvdXQgdHlwZXMuXG4gIGNvbnN0IGlucHV0OiBEb2NrZXJDb21wb3NlRmlsZVNjaGVtYSA9IHtcbiAgICB2ZXJzaW9uLFxuICAgIHNlcnZpY2VzLFxuICAgIC4uLihPYmplY3Qua2V5cyh2b2x1bWVDb25maWcpLmxlbmd0aCA+IDAgPyB7IHZvbHVtZXM6IHZvbHVtZUNvbmZpZyB9IDoge30pLFxuICB9O1xuXG4gIC8vIENoYW5nZSBtb3N0IGtleXMgdG8gc25ha2UgY2FzZS5cbiAgcmV0dXJuIGRlY2FtZWxpemVLZXlzUmVjdXJzaXZlbHkoaW5wdXQsIHtcbiAgICBzaG91bGREZWNhbWVsaXplOiBzaG91bGREZWNhbWVsaXplRG9ja2VyQ29tcG9zZUtleSxcbiAgICBzZXBhcmF0b3I6IFwiX1wiLFxuICB9KTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGB7IFtrZXldOiB2YWx1ZSB9YCBpZiBgdmFsdWVgIGlzIGRlZmluZWQsIG90aGVyd2lzZSByZXR1cm5zIGB7fWAgc29cbiAqIHRoYXQgb2JqZWN0IHNwcmVhZGluZyBjYW4gYmUgdXNlZCB0byBnZW5lcmF0ZSBhIHBlY3VsaWFyIGludGVyZmFjZS5cbiAqIEBwYXJhbSBrZXlcbiAqIEBwYXJhbSB2YWx1ZVxuICovXG5mdW5jdGlvbiBnZXRPYmplY3RXaXRoS2V5QW5kVmFsdWVJZlZhbHVlSXNEZWZpbmVkPEsgZXh0ZW5kcyBzdHJpbmcsIFQ+KFxuICBrZXk6IEssXG4gIHZhbHVlOiBUXG4pOiB7IEs6IFQgfSB8IHt9IHtcbiAgcmV0dXJuIHZhbHVlICE9PSB1bmRlZmluZWQgPyB7IFtrZXldOiB2YWx1ZSB9IDoge307XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBrZXkgYXQgdGhlIGdpdmVuIHBhdGggc2hvdWxkIGJlIGRlY2FtZWxpemVkLlxuICogTGFyZ2VseSwgYWxsIGtleXMgc2hvdWxkIGJlIHNuYWtlIGNhc2VkLiBCdXQsIHRoZXJlIGFyZSBzb21lXG4gKiBleGNlcHRpb25zIGZvciB1c2VyLXByb3ZpZGVkIG5hbWVzIGZvciBzZXJ2aWNlcywgdm9sdW1lcywgYW5kXG4gKiBlbnZpcm9ubWVudCB2YXJpYWJsZXMuXG4gKlxuICogQHBhcmFtIHBhdGhcbiAqL1xuZnVuY3Rpb24gc2hvdWxkRGVjYW1lbGl6ZURvY2tlckNvbXBvc2VLZXkocGF0aDogc3RyaW5nW10pIHtcbiAgY29uc3QgcG91bmRQYXRoID0gcGF0aC5qb2luKFwiI1wiKTtcblxuICAvLyBEb2VzIG5vdCBkZWNhbWVsaXplIHVzZXIncyBuYW1lcy5cbiAgLy8gc2VydmljZXMubmFtZWhlcmU6XG4gIC8vIHZvbHVtZXMubmFtZWhlcmU6XG4gIGlmICgvXihzZXJ2aWNlc3x2b2x1bWVzKSNbXiNdKyQvLnRlc3QocG91bmRQYXRoKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIERvZXMgbm90IGRlY2FtZWxpemUgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gIC8vIHNlcnZpY2VzLm5hbWVoZXJlLmVudmlyb25tZW50LipcbiAgaWYgKC9ec2VydmljZXMjW14jXSsjZW52aXJvbm1lbnQjLy50ZXN0KHBvdW5kUGF0aCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBEb2VzIG5vdCBkZWNhbWVsaXplIGJ1aWxkIGFyZ3VtZW50c1xuICAvLyBzZXJ2aWNlcy5uYW1laGVyZS5idWlsZC5hcmdzLipcbiAgaWYgKC9ec2VydmljZXMjW14jXSsjYnVpbGQjYXJncyMvLnRlc3QocG91bmRQYXRoKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIE90aGVyd2lzZSwgbGV0IGl0IGFsbCBkZWNhbWVsaXplLlxuICByZXR1cm4gdHJ1ZTtcbn1cbiJdfQ==
|