@fjall/components-infrastructure 0.88.4 → 0.89.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/dist/lib/config/aws/disasterRecovery.js +28 -7
  3. package/dist/lib/patterns/aws/compute.d.ts +6 -716
  4. package/dist/lib/patterns/aws/compute.js +24 -427
  5. package/dist/lib/patterns/aws/computeEc2.d.ts +67 -0
  6. package/dist/lib/patterns/aws/computeEc2.js +46 -0
  7. package/dist/lib/patterns/aws/computeEcs.d.ts +446 -0
  8. package/dist/lib/patterns/aws/computeEcs.js +246 -0
  9. package/dist/lib/patterns/aws/computeLambda.d.ts +220 -0
  10. package/dist/lib/patterns/aws/computeLambda.js +147 -0
  11. package/dist/lib/patterns/aws/domainDelegation.d.ts +8 -0
  12. package/dist/lib/patterns/aws/domainDelegation.js +54 -0
  13. package/dist/lib/patterns/aws/domainFactory.d.ts +8 -0
  14. package/dist/lib/patterns/aws/domainFactory.js +23 -0
  15. package/dist/lib/patterns/aws/index.d.ts +3 -0
  16. package/dist/lib/patterns/aws/index.js +5 -1
  17. package/dist/lib/patterns/aws/interfaces/domain.d.ts +2 -0
  18. package/dist/lib/patterns/aws/interfaces/domain.js +6 -0
  19. package/dist/lib/patterns/aws/interfaces/index.d.ts +1 -0
  20. package/dist/lib/patterns/aws/interfaces/index.js +1 -1
  21. package/dist/lib/patterns/aws/interfaces/pattern.d.ts +3 -0
  22. package/dist/lib/patterns/aws/interfaces/pattern.js +1 -1
  23. package/dist/lib/patterns/aws/payload.js +11 -1
  24. package/dist/lib/resources/aws/compute/ecs.d.ts +14 -2
  25. package/dist/lib/resources/aws/compute/ecs.js +69 -24
  26. package/dist/lib/resources/aws/networking/domain.d.ts +13 -0
  27. package/dist/lib/resources/aws/networking/domain.js +102 -0
  28. package/dist/lib/resources/aws/networking/domainCertificate.d.ts +13 -0
  29. package/dist/lib/resources/aws/networking/domainCertificate.js +28 -0
  30. package/dist/lib/resources/aws/networking/hostedZone.js +3 -6
  31. package/dist/lib/resources/aws/networking/index.d.ts +2 -0
  32. package/dist/lib/resources/aws/networking/index.js +3 -1
  33. package/dist/lib/utils/capitaliseString.d.ts +1 -18
  34. package/dist/lib/utils/capitaliseString.js +8 -37
  35. package/dist/lib/utils/dnsRecords.d.ts +4 -0
  36. package/dist/lib/utils/dnsRecords.js +108 -0
  37. package/dist/lib/utils/domainTypes.d.ts +37 -0
  38. package/dist/lib/utils/domainTypes.js +10 -0
  39. package/dist/lib/utils/env.js +23 -29
  40. package/dist/lib/utils/getConfig.js +42 -16
  41. package/dist/lib/utils/index.d.ts +1 -0
  42. package/dist/lib/utils/index.js +2 -1
  43. package/package.json +4 -3
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EcsCompute = exports.ECS_CAPACITY_PROVIDER_CONFIG = exports.ScalingType = void 0;
4
+ exports.getEcsCapacityProviderConfig = getEcsCapacityProviderConfig;
5
+ exports.validateEcsProps = validateEcsProps;
6
+ exports.buildContainerConfigs = buildContainerConfigs;
7
+ exports.resolveScalingConfig = resolveScalingConfig;
8
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
9
+ const constructs_1 = require("constructs");
10
+ const ecs_1 = require("../../resources/aws/compute/ecs");
11
+ Object.defineProperty(exports, "ScalingType", { enumerable: true, get: function () { return ecs_1.ScalingType; } });
12
+ const validationLogger_js_1 = require("../../utils/validationLogger.js");
13
+ const compute_js_1 = require("./compute.js");
14
+ exports.ECS_CAPACITY_PROVIDER_CONFIG = {
15
+ FARGATE: {
16
+ usesSpot: false,
17
+ usesEc2Instances: false
18
+ },
19
+ FARGATE_SPOT: {
20
+ usesSpot: true,
21
+ usesEc2Instances: false
22
+ },
23
+ EC2: {
24
+ usesSpot: false,
25
+ usesEc2Instances: true
26
+ }
27
+ };
28
+ function getEcsCapacityProviderConfig(provider) {
29
+ return exports.ECS_CAPACITY_PROVIDER_CONFIG[provider];
30
+ }
31
+ /**
32
+ * Validates ECS-specific props.
33
+ * Extracted for clarity and detail parity with database/network patterns.
34
+ */
35
+ function validateEcsProps(props) {
36
+ // Validate services array exists and is not empty
37
+ if (!props.services || props.services.length === 0) {
38
+ throw new Error("At least one service must be specified in 'services' array.");
39
+ }
40
+ // Validate unique service names
41
+ const serviceNames = props.services.map((s) => s.name);
42
+ const duplicateNames = serviceNames.filter((name, index) => serviceNames.indexOf(name) !== index);
43
+ if (duplicateNames.length > 0) {
44
+ throw new Error(`Duplicate service names: ${[...new Set(duplicateNames)].join(", ")}`);
45
+ }
46
+ // Validate service name format
47
+ const invalidNames = props.services.filter((s) => !/^[a-zA-Z][a-zA-Z0-9-]*$/.test(s.name));
48
+ if (invalidNames.length > 0) {
49
+ throw new Error(`Invalid service names: ${invalidNames.map((s) => s.name).join(", ")}. ` +
50
+ "Service names must start with a letter and contain only letters, numbers, and hyphens.");
51
+ }
52
+ // Validate routing when multiple services have ports
53
+ const servicesWithPorts = props.services.filter((s) => s.containers?.some((c) => c.port));
54
+ if (servicesWithPorts.length > 1) {
55
+ const missingRouting = servicesWithPorts.filter((s) => {
56
+ const rules = Array.isArray(s.routing)
57
+ ? s.routing
58
+ : s.routing
59
+ ? [s.routing]
60
+ : [];
61
+ return !rules.some((r) => r.path || r.host);
62
+ });
63
+ if (missingRouting.length > 0) {
64
+ throw new Error(`Services with ports require routing config when cluster has multiple services: ` +
65
+ `${missingRouting.map((s) => s.name).join(", ")}. ` +
66
+ "Add routing: { path: '/...' } or routing: { host: '...' } to each service.");
67
+ }
68
+ }
69
+ // Validate each service's containers
70
+ for (const service of props.services) {
71
+ if (service.containers && service.containers.length > 0) {
72
+ // Check for duplicate container names within service (only named containers)
73
+ const containerNames = service.containers
74
+ .filter((c) => c.name)
75
+ .map((c) => c.name);
76
+ const duplicateContainerNames = containerNames.filter((name, index) => containerNames.indexOf(name) !== index);
77
+ if (duplicateContainerNames.length > 0) {
78
+ throw new Error(`Service '${service.name}': Duplicate container names: ` +
79
+ `${[...new Set(duplicateContainerNames)].join(", ")}`);
80
+ }
81
+ }
82
+ if (service.capacityProvider === "EC2" && !service.ec2Config) {
83
+ throw new Error(`Service '${service.name}' uses EC2 capacity provider but no ec2Config is defined. ` +
84
+ "Provide ec2Config on the service.");
85
+ }
86
+ // Warn if service ec2Config is defined but capacityProvider is not EC2
87
+ if (service.ec2Config && service.capacityProvider !== "EC2") {
88
+ validationLogger_js_1.FjallLogger.warn(`Service '${service.name}' has ec2Config but capacityProvider is not 'EC2'. ` +
89
+ "The ec2Config will be ignored unless capacityProvider is set to 'EC2'.");
90
+ }
91
+ }
92
+ }
93
+ /**
94
+ * Build container configurations for an ECS service.
95
+ * Converts user-facing EcsContainerConfig to internal EcsClusterProps format.
96
+ * @internal Exported for testing only
97
+ */
98
+ function buildContainerConfigs(service) {
99
+ if (service.containers && service.containers.length > 0) {
100
+ return service.containers.map((c, index) => ({
101
+ name: c.name || `${service.name}Container${index > 0 ? index : ""}`,
102
+ image: c.image,
103
+ port: c.port,
104
+ environment: c.environment,
105
+ secrets: c.secrets,
106
+ secretsImport: c.secretsImport,
107
+ command: c.command,
108
+ entryPoint: c.entryPoint,
109
+ essential: c.essential,
110
+ healthCheck: c.healthCheck
111
+ }));
112
+ }
113
+ // Default container (no port = worker)
114
+ return [{ name: `${service.name}Container` }];
115
+ }
116
+ /**
117
+ * Resolve scaling configuration from service props.
118
+ * Handles the three cases: explicit config, disabled (false), or default (undefined).
119
+ * @internal Exported for testing only
120
+ */
121
+ function resolveScalingConfig(scaling) {
122
+ if (scaling === false) {
123
+ return {
124
+ scalingType: undefined,
125
+ minCapacity: undefined,
126
+ maxCapacity: undefined
127
+ };
128
+ }
129
+ if (scaling === undefined) {
130
+ return {
131
+ scalingType: ecs_1.ScalingType.CPU,
132
+ minCapacity: undefined,
133
+ maxCapacity: undefined
134
+ };
135
+ }
136
+ return {
137
+ scalingType: scaling.scalingType ?? ecs_1.ScalingType.CPU,
138
+ minCapacity: scaling.minCapacity,
139
+ maxCapacity: scaling.maxCapacity
140
+ };
141
+ }
142
+ /**
143
+ * ECS compute wrapper implementing IEcsCompute.
144
+ * Provides type-safe access to ECS-specific resources.
145
+ */
146
+ class EcsCompute extends constructs_1.Construct {
147
+ constructor(scope, id, props) {
148
+ super(scope, id);
149
+ this.computeType = "ecs";
150
+ // Transform EcsServiceConfig[] to EcsServiceProps[] for EcsCluster
151
+ const services = props.services.map((service) => {
152
+ const containers = buildContainerConfigs(service);
153
+ const { scalingType, minCapacity, maxCapacity } = resolveScalingConfig(service.scaling);
154
+ return {
155
+ name: service.name,
156
+ image: service.image,
157
+ containers,
158
+ cpu: service.cpu,
159
+ memoryLimitMiB: service.memoryLimitMiB,
160
+ desiredCount: service.desiredCount,
161
+ scalingType,
162
+ minCapacity,
163
+ maxCapacity,
164
+ routing: service.routing,
165
+ taskRoleInlinePolicies: service.taskRoleInlinePolicies,
166
+ taskRoleManagedPolicies: service.taskRoleManagedPolicies,
167
+ connections: service.connections,
168
+ capacityProvider: service.capacityProvider,
169
+ ec2Config: service.ec2Config,
170
+ ssmSecretsPath: service.ssmSecretsPath,
171
+ dockerTarget: service.dockerTarget
172
+ };
173
+ });
174
+ // Build cluster config
175
+ const cluster = props.cluster
176
+ ? {
177
+ domain: props.cluster.domain,
178
+ loadBalancer: props.cluster.loadBalancer,
179
+ directAccess: props.cluster.directAccess,
180
+ domainConfig: props.cluster.domainConfig
181
+ }
182
+ : undefined;
183
+ const ecsProps = {
184
+ clusterName: id,
185
+ appName: props.appName,
186
+ vpc: props.vpc,
187
+ ecrRepository: props.ecrRepository || compute_js_1.COMPUTE_DEFAULTS.ECS.FALLBACK_IMAGE,
188
+ cluster,
189
+ services
190
+ };
191
+ this.ecsCluster = new ecs_1.default(scope, `${id}Ecs`, ecsProps);
192
+ this.connections = this.ecsCluster.connections;
193
+ }
194
+ /** Get the ECS cluster. */
195
+ getCluster() {
196
+ return this.ecsCluster.getCluster();
197
+ }
198
+ /** Get the Application Load Balancer if one was created. */
199
+ getLoadBalancer() {
200
+ return this.ecsCluster.getLoadBalancer();
201
+ }
202
+ /** Get a specific service by name. */
203
+ getService(name) {
204
+ return this.ecsCluster.getService(name);
205
+ }
206
+ /** Get all services in the cluster. */
207
+ getAllServices() {
208
+ const servicesMap = this.ecsCluster.getServices();
209
+ return Array.from(servicesMap.values());
210
+ }
211
+ /** Get the security group for the cluster. */
212
+ getSecurityGroup() {
213
+ // Return the first security group from connections
214
+ const securityGroups = this.connections.securityGroups;
215
+ if (securityGroups.length === 0) {
216
+ throw new Error("No security groups found for ECS cluster");
217
+ }
218
+ return securityGroups[0];
219
+ }
220
+ /**
221
+ * Get the ALB listener if this is an ECS compute with ALB.
222
+ */
223
+ getListener() {
224
+ return this.ecsCluster.getListener();
225
+ }
226
+ /**
227
+ * Get the underlying ECS cluster construct.
228
+ */
229
+ getEcsCluster() {
230
+ return this.ecsCluster;
231
+ }
232
+ /**
233
+ * Grants ecs:ExecuteCommand permission for ECS services.
234
+ * Uses wildcard resource because ecs:ExecuteCommand targets task ARNs
235
+ * which are not known until runtime (tasks are ephemeral).
236
+ */
237
+ grantExecuteCommand(grantee) {
238
+ return aws_iam_1.Grant.addToPrincipal({
239
+ grantee,
240
+ actions: ["ecs:ExecuteCommand"],
241
+ resourceArns: ["*"]
242
+ });
243
+ }
244
+ }
245
+ exports.EcsCompute = EcsCompute;
246
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcHV0ZUVjcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9wYXR0ZXJucy9hd3MvY29tcHV0ZUVjcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUF1RUEsb0VBSUM7QUFpWkQsNENBc0ZDO0FBT0Qsc0RBbUJDO0FBaUJELG9EQXNCQztBQXhtQkQsaURBSzZCO0FBTTdCLDJDQUF1QztBQUt2Qyx5REFNeUM7QUFPaEMsNEZBWFAsaUJBQVcsT0FXTztBQUxwQix5RUFBOEQ7QUFFOUQsNkNBQWdEO0FBZ0JuQyxRQUFBLDRCQUE0QixHQUdyQztJQUNGLE9BQU8sRUFBRTtRQUNQLFFBQVEsRUFBRSxLQUFLO1FBQ2YsZ0JBQWdCLEVBQUUsS0FBSztLQUN4QjtJQUNELFlBQVksRUFBRTtRQUNaLFFBQVEsRUFBRSxJQUFJO1FBQ2QsZ0JBQWdCLEVBQUUsS0FBSztLQUN4QjtJQUNELEdBQUcsRUFBRTtRQUNILFFBQVEsRUFBRSxLQUFLO1FBQ2YsZ0JBQWdCLEVBQUUsSUFBSTtLQUN2QjtDQUNGLENBQUM7QUFFRixTQUFnQiw0QkFBNEIsQ0FDMUMsUUFBNkI7SUFFN0IsT0FBTyxvQ0FBNEIsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBNllEOzs7R0FHRztBQUNILFNBQWdCLGdCQUFnQixDQUFDLEtBQXNCO0lBQ3JELGtEQUFrRDtJQUNsRCxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNuRCxNQUFNLElBQUksS0FBSyxDQUNiLDZEQUE2RCxDQUM5RCxDQUFDO0lBQ0osQ0FBQztJQUVELGdDQUFnQztJQUNoQyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3ZELE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQ3hDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLENBQ3RELENBQUM7SUFDRixJQUFJLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDOUIsTUFBTSxJQUFJLEtBQUssQ0FDYiw0QkFBNEIsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQ3RFLENBQUM7SUFDSixDQUFDO0lBRUQsK0JBQStCO0lBQy9CLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUN4QyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUMvQyxDQUFDO0lBQ0YsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzVCLE1BQU0sSUFBSSxLQUFLLENBQ2IsMEJBQTBCLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUk7WUFDdEUsd0ZBQXdGLENBQzNGLENBQUM7SUFDSixDQUFDO0lBRUQscURBQXFEO0lBQ3JELE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUNwRCxDQUFDLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUNsQyxDQUFDO0lBRUYsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDakMsTUFBTSxjQUFjLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDcEQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNwQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU87Z0JBQ1gsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO29CQUNULENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7b0JBQ2IsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNULE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM5QixNQUFNLElBQUksS0FBSyxDQUNiLGlGQUFpRjtnQkFDL0UsR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJO2dCQUNuRCw0RUFBNEUsQ0FDL0UsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQscUNBQXFDO0lBQ3JDLEtBQUssTUFBTSxPQUFPLElBQUksS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JDLElBQUksT0FBTyxDQUFDLFVBQVUsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4RCw2RUFBNkU7WUFDN0UsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLFVBQVU7aUJBQ3RDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztpQkFDckIsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEIsTUFBTSx1QkFBdUIsR0FBRyxjQUFjLENBQUMsTUFBTSxDQUNuRCxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxDQUN4RCxDQUFDO1lBQ0YsSUFBSSx1QkFBdUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQ2IsWUFBWSxPQUFPLENBQUMsSUFBSSxnQ0FBZ0M7b0JBQ3RELEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FDeEQsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxPQUFPLENBQUMsZ0JBQWdCLEtBQUssS0FBSyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQzdELE1BQU0sSUFBSSxLQUFLLENBQ2IsWUFBWSxPQUFPLENBQUMsSUFBSSw0REFBNEQ7Z0JBQ2xGLG1DQUFtQyxDQUN0QyxDQUFDO1FBQ0osQ0FBQztRQUVELHVFQUF1RTtRQUN2RSxJQUFJLE9BQU8sQ0FBQyxTQUFTLElBQUksT0FBTyxDQUFDLGdCQUFnQixLQUFLLEtBQUssRUFBRSxDQUFDO1lBQzVELGlDQUFXLENBQUMsSUFBSSxDQUNkLFlBQVksT0FBTyxDQUFDLElBQUkscURBQXFEO2dCQUMzRSx3RUFBd0UsQ0FDM0UsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQixxQkFBcUIsQ0FDbkMsT0FBeUI7SUFFekIsSUFBSSxPQUFPLENBQUMsVUFBVSxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3hELE9BQU8sT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzNDLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksWUFBWSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNuRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUs7WUFDZCxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUk7WUFDWixXQUFXLEVBQUUsQ0FBQyxDQUFDLFdBQVc7WUFDMUIsT0FBTyxFQUFFLENBQUMsQ0FBQyxPQUFPO1lBQ2xCLGFBQWEsRUFBRSxDQUFDLENBQUMsYUFBYTtZQUM5QixPQUFPLEVBQUUsQ0FBQyxDQUFDLE9BQU87WUFDbEIsVUFBVSxFQUFFLENBQUMsQ0FBQyxVQUFVO1lBQ3hCLFNBQVMsRUFBRSxDQUFDLENBQUMsU0FBUztZQUN0QixXQUFXLEVBQUUsQ0FBQyxDQUFDLFdBQVc7U0FDM0IsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO0lBQ0QsdUNBQXVDO0lBQ3ZDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFDaEQsQ0FBQztBQVlEOzs7O0dBSUc7QUFDSCxTQUFnQixvQkFBb0IsQ0FDbEMsT0FBNkM7SUFFN0MsSUFBSSxPQUFPLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDdEIsT0FBTztZQUNMLFdBQVcsRUFBRSxTQUFTO1lBQ3RCLFdBQVcsRUFBRSxTQUFTO1lBQ3RCLFdBQVcsRUFBRSxTQUFTO1NBQ3ZCLENBQUM7SUFDSixDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDMUIsT0FBTztZQUNMLFdBQVcsRUFBRSxpQkFBVyxDQUFDLEdBQUc7WUFDNUIsV0FBVyxFQUFFLFNBQVM7WUFDdEIsV0FBVyxFQUFFLFNBQVM7U0FDdkIsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPO1FBQ0wsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXLElBQUksaUJBQVcsQ0FBQyxHQUFHO1FBQ25ELFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVztRQUNoQyxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVc7S0FDakMsQ0FBQztBQUNKLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFhLFVBQVcsU0FBUSxzQkFBUztJQU12QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXNCO1FBQzlELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFOSCxnQkFBVyxHQUFHLEtBQWMsQ0FBQztRQVEzQyxtRUFBbUU7UUFDbkUsTUFBTSxRQUFRLEdBQWdDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUM5RCxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ1YsTUFBTSxVQUFVLEdBQUcscUJBQXFCLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbEQsTUFBTSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLEdBQUcsb0JBQW9CLENBQ3BFLE9BQU8sQ0FBQyxPQUFPLENBQ2hCLENBQUM7WUFFRixPQUFPO2dCQUNMLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtnQkFDbEIsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO2dCQUNwQixVQUFVO2dCQUNWLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRztnQkFDaEIsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjO2dCQUN0QyxZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVk7Z0JBQ2xDLFdBQVc7Z0JBQ1gsV0FBVztnQkFDWCxXQUFXO2dCQUNYLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztnQkFDeEIsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLHNCQUFzQjtnQkFDdEQsdUJBQXVCLEVBQUUsT0FBTyxDQUFDLHVCQUF1QjtnQkFDeEQsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXO2dCQUNoQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsZ0JBQWdCO2dCQUMxQyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7Z0JBQzVCLGNBQWMsRUFBRSxPQUFPLENBQUMsY0FBYztnQkFDdEMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO2FBQ25DLENBQUM7UUFDSixDQUFDLENBQ0YsQ0FBQztRQUVGLHVCQUF1QjtRQUN2QixNQUFNLE9BQU8sR0FBK0IsS0FBSyxDQUFDLE9BQU87WUFDdkQsQ0FBQyxDQUFDO2dCQUNFLE1BQU0sRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU07Z0JBQzVCLFlBQVksRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVk7Z0JBQ3hDLFlBQVksRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVk7Z0JBQ3hDLFlBQVksRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVk7YUFDekM7WUFDSCxDQUFDLENBQUMsU0FBUyxDQUFDO1FBRWQsTUFBTSxRQUFRLEdBQW9CO1lBQ2hDLFdBQVcsRUFBRSxFQUFFO1lBQ2YsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRztZQUNkLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLDZCQUFnQixDQUFDLEdBQUcsQ0FBQyxjQUFjO1lBQ3pFLE9BQU87WUFDUCxRQUFRO1NBQ1QsQ0FBQztRQUVGLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxhQUFVLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQztJQUNqRCxDQUFDO0lBRUQsMkJBQTJCO0lBQzNCLFVBQVU7UUFDUixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDdEMsQ0FBQztJQUVELDREQUE0RDtJQUM1RCxlQUFlO1FBQ2IsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRCxzQ0FBc0M7SUFDdEMsVUFBVSxDQUFDLElBQVk7UUFDckIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQsdUNBQXVDO0lBQ3ZDLGNBQWM7UUFDWixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2xELE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQsOENBQThDO0lBQzlDLGdCQUFnQjtRQUNkLG1EQUFtRDtRQUNuRCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQztRQUN2RCxJQUFJLGNBQWMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDaEMsTUFBTSxJQUFJLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFDRCxPQUFPLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7T0FFRztJQUNILGFBQWE7UUFDWCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDekIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxtQkFBbUIsQ0FBQyxPQUFtQjtRQUNyQyxPQUFPLGVBQUssQ0FBQyxjQUFjLENBQUM7WUFDMUIsT0FBTztZQUNQLE9BQU8sRUFBRSxDQUFDLG9CQUFvQixDQUFDO1lBQy9CLFlBQVksRUFBRSxDQUFDLEdBQUcsQ0FBQztTQUNwQixDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUF2SEQsZ0NBdUhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgdHlwZSBSZXBvc2l0b3J5SW1hZ2UsXG4gIHR5cGUgSUNsdXN0ZXIsXG4gIHR5cGUgSUJhc2VTZXJ2aWNlXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWNzXCI7XG5pbXBvcnQgeyB0eXBlIFJlcG9zaXRvcnkgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjclwiO1xuaW1wb3J0IHtcbiAgdHlwZSBDb25uZWN0aW9ucyxcbiAgdHlwZSBJVnBjLFxuICB0eXBlIElTZWN1cml0eUdyb3VwXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWMyXCI7XG5pbXBvcnQge1xuICB0eXBlIFBvbGljeURvY3VtZW50LFxuICB0eXBlIElNYW5hZ2VkUG9saWN5LFxuICB0eXBlIElHcmFudGFibGUsXG4gIEdyYW50XG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQge1xuICB0eXBlIElBcHBsaWNhdGlvbkxvYWRCYWxhbmNlcixcbiAgdHlwZSBBcHBsaWNhdGlvbkxpc3RlbmVyXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWxhc3RpY2xvYWRiYWxhbmNpbmd2MlwiO1xuXG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuXG5pbXBvcnQgeyB0eXBlIElFY3NDb21wdXRlIH0gZnJvbSBcIi4vaW50ZXJmYWNlcy9jb21wdXRlLmpzXCI7XG5pbXBvcnQgeyB0eXBlIENvbm5lY3Rpb25TcGVjIH0gZnJvbSBcIi4vaW50ZXJmYWNlcy9jb25uZWN0b3IuanNcIjtcblxuaW1wb3J0IEVjc0NsdXN0ZXIsIHtcbiAgdHlwZSBFY3NDbHVzdGVyUHJvcHMsXG4gIFNjYWxpbmdUeXBlLFxuICB0eXBlIERvbWFpbkNvbmZpZyxcbiAgdHlwZSBFY3NDYXBhY2l0eVByb3ZpZGVyLFxuICB0eXBlIEVjMkNhcGFjaXR5Q29uZmlnXG59IGZyb20gXCIuLi8uLi9yZXNvdXJjZXMvYXdzL2NvbXB1dGUvZWNzXCI7XG5pbXBvcnQgeyB0eXBlIFNlY3JldEltcG9ydCB9IGZyb20gXCIuLi8uLi9yZXNvdXJjZXMvYXdzL3NlY3JldHNcIjtcbmltcG9ydCB7IEZqYWxsTG9nZ2VyIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3ZhbGlkYXRpb25Mb2dnZXIuanNcIjtcblxuaW1wb3J0IHsgQ09NUFVURV9ERUZBVUxUUyB9IGZyb20gXCIuL2NvbXB1dGUuanNcIjtcblxuLy8gUmUtZXhwb3J0IGZyb20gZWNzLnRzIHRvIG1haW50YWluIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGhcbmV4cG9ydCB7IFNjYWxpbmdUeXBlIH07XG5leHBvcnQgdHlwZSB7IEVjc0NhcGFjaXR5UHJvdmlkZXIsIEVjMkNhcGFjaXR5Q29uZmlnIH07XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgRUNTIGNhcGFjaXR5IHByb3ZpZGVycy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFY3NDYXBhY2l0eVByb3ZpZGVyQ29uZmlnIHtcbiAgLyoqIFdoZXRoZXIgdGhpcyB1c2VzIFNwb3QgcHJpY2luZyAqL1xuICB1c2VzU3BvdDogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdGhpcyBydW5zIG9uIEVDMiBpbnN0YW5jZXMgKHZzIHNlcnZlcmxlc3MgRmFyZ2F0ZSkgKi9cbiAgdXNlc0VjMkluc3RhbmNlczogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNvbnN0IEVDU19DQVBBQ0lUWV9QUk9WSURFUl9DT05GSUc6IFJlY29yZDxcbiAgRWNzQ2FwYWNpdHlQcm92aWRlcixcbiAgRWNzQ2FwYWNpdHlQcm92aWRlckNvbmZpZ1xuPiA9IHtcbiAgRkFSR0FURToge1xuICAgIHVzZXNTcG90OiBmYWxzZSxcbiAgICB1c2VzRWMySW5zdGFuY2VzOiBmYWxzZVxuICB9LFxuICBGQVJHQVRFX1NQT1Q6IHtcbiAgICB1c2VzU3BvdDogdHJ1ZSxcbiAgICB1c2VzRWMySW5zdGFuY2VzOiBmYWxzZVxuICB9LFxuICBFQzI6IHtcbiAgICB1c2VzU3BvdDogZmFsc2UsXG4gICAgdXNlc0VjMkluc3RhbmNlczogdHJ1ZVxuICB9XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWNzQ2FwYWNpdHlQcm92aWRlckNvbmZpZyhcbiAgcHJvdmlkZXI6IEVjc0NhcGFjaXR5UHJvdmlkZXJcbik6IEVjc0NhcGFjaXR5UHJvdmlkZXJDb25maWcge1xuICByZXR1cm4gRUNTX0NBUEFDSVRZX1BST1ZJREVSX0NPTkZJR1twcm92aWRlcl07XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgYSBjb250YWluZXIgaW4gYW4gRUNTIHRhc2suXG4gKlxuICogRm9yIHNpbmdsZS1jb250YWluZXIgc2VydmljZXMsIGBuYW1lYCBpcyBvcHRpb25hbCBhbmQgZGVmYXVsdHMgdG8gYCR7c2VydmljZU5hbWV9Q29udGFpbmVyYC5cbiAqIEZvciBtdWx0aS1jb250YWluZXIgdGFza3MsIHRoZSBmaXJzdCBjb250YWluZXIgd2l0aCBhIGBwb3J0YCBpcyB0aGUgKipwcmltYXJ5IGNvbnRhaW5lcioqXG4gKiB0aGF0IHJlY2VpdmVzIGxvYWQgYmFsYW5jZXIgdHJhZmZpYy5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gU2luZ2xlIGNvbnRhaW5lciAobmFtZSBhdXRvLWdlbmVyYXRlZClcbiAqIGNvbnRhaW5lcnM6IFt7IHBvcnQ6IDMwMDAgfV1cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gTXVsdGktY29udGFpbmVyIHdpdGggc2lkZWNhcnNcbiAqIGNvbnRhaW5lcnM6IFtcbiAqICAgeyBuYW1lOiBcImFwcFwiLCBwb3J0OiAzMDAwIH0sICAgICAgICAgICAgICAgICAgICAvLyBQcmltYXJ5IC0gcmVjZWl2ZXMgQUxCIHRyYWZmaWNcbiAqICAgeyBuYW1lOiBcImRhdGFkb2dcIiwgaW1hZ2U6IFwiZGF0YWRvZy9hZ2VudFwiIH0gICAgIC8vIFNpZGVjYXIgLSBtb25pdG9yaW5nXG4gKiBdXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWNzQ29udGFpbmVyQ29uZmlnIHtcbiAgLyoqIENvbnRhaW5lciBuYW1lLiBPcHRpb25hbCBmb3Igc2luZ2xlLWNvbnRhaW5lciBzZXJ2aWNlcy4gKi9cbiAgbmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAqIENvbnRhaW5lciBpbWFnZS4gT3B0aW9uczpcbiAgICogLSBPbWl0OiBVc2VzIGFwcCdzIGRlZmF1bHQgRUNSIHJlcG9zaXRvcnkgKHByaW1hcnkgY29udGFpbmVyIG9ubHkpXG4gICAqIC0gc3RyaW5nOiBFQ1IgcmVwb3NpdG9yeSBuYW1lIG9yIHB1YmxpYyBpbWFnZSBVUkxcbiAgICogLSBSZXBvc2l0b3J5OiBDREsgRUNSIFJlcG9zaXRvcnkgY29uc3RydWN0XG4gICAqL1xuICBpbWFnZT86IHN0cmluZyB8IFJlcG9zaXRvcnk7XG4gIC8qKlxuICAgKiBQb3J0IHRoZSBjb250YWluZXIgbGlzdGVucyBvbi5cbiAgICogVGhlIGZpcnN0IGNvbnRhaW5lciB3aXRoIGEgcG9ydCBiZWNvbWVzIHRoZSAqKnByaW1hcnkgY29udGFpbmVyKipcbiAgICogYW5kIGlzIHJlZ2lzdGVyZWQgd2l0aCB0aGUgbG9hZCBiYWxhbmNlci5cbiAgICovXG4gIHBvcnQ/OiBudW1iZXI7XG4gIC8qKiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgKi9cbiAgZW52aXJvbm1lbnQ/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAvKipcbiAgICogU2VjcmV0cyBmcm9tIEFXUyBTU00gUGFyYW1ldGVyIFN0b3JlLlxuICAgKiBBcnJheSBvZiBzZWNyZXQgbmFtZXMgdGhhdCB3aWxsIGJlIGZldGNoZWQgZnJvbSB0aGUgc2VydmljZSdzIFNTTSBuYW1lc3BhY2UuXG4gICAqIFRoZSBuYW1lc3BhY2UgcGF0aCBpcyBhdXRvLWRldGVybWluZWQgZnJvbSBhcHAvY2x1c3Rlci9zZXJ2aWNlIG5hbWVzLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBTZWNyZXRzIGF0IC9teWFwcC9hcGktY2x1c3Rlci91c2Vycy9BUElfS0VZIGFuZCAvbXlhcHAvYXBpLWNsdXN0ZXIvdXNlcnMvREJfUEFTU1dPUkRcbiAgICogc2VjcmV0czogW1wiQVBJX0tFWVwiLCBcIkRCX1BBU1NXT1JEXCJdXG4gICAqL1xuICBzZWNyZXRzPzogc3RyaW5nW107XG4gIC8qKiBTZWNyZXRzIGltcG9ydGVkIGZyb20gb3RoZXIgQ0RLIHJlc291cmNlcyAoQVdTIFNlY3JldHMgTWFuYWdlcikgKi9cbiAgc2VjcmV0c0ltcG9ydD86IFJlY29yZDxzdHJpbmcsIFNlY3JldEltcG9ydD47XG4gIC8qKiBDb21tYW5kIHRvIHJ1biBpbiB0aGUgY29udGFpbmVyICovXG4gIGNvbW1hbmQ/OiBzdHJpbmdbXTtcbiAgLyoqIEVudHJ5IHBvaW50IGZvciB0aGUgY29udGFpbmVyICovXG4gIGVudHJ5UG9pbnQ/OiBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBjb250YWluZXIgaXMgZXNzZW50aWFsLlxuICAgKiBJZiBhbiBlc3NlbnRpYWwgY29udGFpbmVyIHN0b3BzLCBhbGwgY29udGFpbmVycyBpbiB0aGUgdGFzayBzdG9wLlxuICAgKiBEZWZhdWx0OiB0cnVlXG4gICAqL1xuICBlc3NlbnRpYWw/OiBib29sZWFuO1xuICAvKipcbiAgICogSGVhbHRoIGNoZWNrIGNvbmZpZ3VyYXRpb24uXG4gICAqIERlZmF1bHQ6IEZvciBwcmltYXJ5IGNvbnRhaW5lciB3aXRoIHBvcnQsIHVzZXMgY3VybCBoZWFsdGggY2hlY2suXG4gICAqL1xuICBoZWFsdGhDaGVjaz86IHtcbiAgICBjb21tYW5kOiBzdHJpbmdbXTtcbiAgICBpbnRlcnZhbD86IG51bWJlcjtcbiAgICB0aW1lb3V0PzogbnVtYmVyO1xuICAgIHJldHJpZXM/OiBudW1iZXI7XG4gICAgc3RhcnRQZXJpb2Q/OiBudW1iZXI7XG4gIH07XG59XG5cbi8qKlxuICogRUNTIHNjYWxpbmcgY29uZmlndXJhdGlvbi5cbiAqIC0gT21pdDogZW5hYmxlZCB3aXRoIGRlZmF1bHRzXG4gKiAtIGB7fWA6IGVuYWJsZWQgd2l0aCBkZWZhdWx0c1xuICogLSBgeyBtaW5DYXBhY2l0eTogMiwgbWF4Q2FwYWNpdHk6IDEwIH1gOiBjdXN0b20gc2NhbGluZ1xuICogLSBgZmFsc2VgOiBleHBsaWNpdGx5IGRpc2FibGVkXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWNzU2NhbGluZ0NvbmZpZyB7XG4gIG1pbkNhcGFjaXR5PzogbnVtYmVyO1xuICBtYXhDYXBhY2l0eT86IG51bWJlcjtcbiAgc2NhbGluZ1R5cGU/OiBTY2FsaW5nVHlwZTtcbn1cblxuLyoqXG4gKiBDbHVzdGVyLWxldmVsIGNvbmZpZ3VyYXRpb24uXG4gKiBDb250cm9scyB0aGUgc2hhcmVkIEFMQiBmb3IgYWxsIHNlcnZpY2VzIGluIHRoaXMgY2x1c3Rlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFY3NDbHVzdGVyQ29uZmlnIHtcbiAgLyoqXG4gICAqIERvbWFpbiBmb3IgSFRUUFMgYWNjZXNzLlxuICAgKiAtIE9taXQ6IEFMQiBjcmVhdGVkIHdpdGggZGVmYXVsdCBETlMgKCouZWxiLmFtYXpvbmF3cy5jb20pXG4gICAqIC0gU3BlY2lmaWVkOiBDcmVhdGVzIEFDTSBjZXJ0aWZpY2F0ZSArIFJvdXRlNTMgRE5TIEEgcmVjb3JkXG4gICAqL1xuICBkb21haW4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIExvYWQgYmFsYW5jZXIgY29uZmlndXJhdGlvbi5cbiAgICogLSBPbWl0IG9yIFwicHVibGljXCI6IEludGVybmV0LWZhY2luZyBBTEIgKGRlZmF1bHQpXG4gICAqIC0gXCJpbnRlcm5hbFwiOiBWUEMtb25seSBBTEJcbiAgICogLSBmYWxzZTogTm8gQUxCIChmb3Igd29ya2Vycy9iYWNrZ3JvdW5kIHByb2Nlc3NvcnMpXG4gICAqL1xuICBsb2FkQmFsYW5jZXI/OiBmYWxzZSB8IFwicHVibGljXCIgfCBcImludGVybmFsXCI7XG5cbiAgLyoqXG4gICAqIEVuYWJsZSBkaXJlY3QgRUMyIGFjY2VzcyB3aXRob3V0IEFMQi5cbiAgICogVXNlcyBob3N0IG5ldHdvcmsgbW9kZSBmb3IgcHJlZGljdGFibGUgcG9ydHMuXG4gICAqIEFjY2VzcyB2aWEgRUMyIHB1YmxpYyBJUCBhdCBjb250YWluZXIgcG9ydC5cbiAgICovXG4gIGRpcmVjdEFjY2Vzcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEFkdmFuY2VkIGRvbWFpbiBjb25maWd1cmF0aW9uIGZvciByb3V0aW5nIHBvbGljaWVzIChsYXRlbmN5LCB3ZWlnaHRlZCwgZ2VvKS5cbiAgICogT25seSB1c2VkIHdoZW4gZG9tYWluIGlzIHNwZWNpZmllZC5cbiAgICogQWxsb3dzIGZvciBtdWx0aS1yZWdpb24gZGVwbG95bWVudHMgd2l0aCBhZHZhbmNlZCBETlMgcm91dGluZy5cbiAgICovXG4gIGRvbWFpbkNvbmZpZz86IERvbWFpbkNvbmZpZztcbn1cblxuLyoqXG4gKiBSb3V0aW5nIGNvbmZpZ3VyYXRpb24gZm9yIHBhdGgvaG9zdC1iYXNlZCByb3V0aW5nIG9uIHRoZSBBTEIuXG4gKiBSZXF1aXJlZCB3aGVuIGNsdXN0ZXIgaGFzIG11bHRpcGxlIHNlcnZpY2VzIHdpdGggcG9ydHMuXG4gKiBPcHRpb25hbCBmb3Igc2luZ2xlIHNlcnZpY2UgKGdldHMgYWxsIHRyYWZmaWMgYXV0b21hdGljYWxseSkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWNzUm91dGluZ0NvbmZpZyB7XG4gIC8qKlxuICAgKiBQYXRoIHBhdHRlcm4gZm9yIHJvdXRpbmcgKGUuZy4sIFwiL2FwaS8qXCIsIFwiL3VzZXJzLypcIikuXG4gICAqIFVzZXMgQUxCIHBhdGgtYmFzZWQgcm91dGluZy5cbiAgICovXG4gIHBhdGg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEhvc3QgaGVhZGVyIGZvciByb3V0aW5nIChlLmcuLCBcImFwaS5leGFtcGxlLmNvbVwiKS5cbiAgICogVXNlcyBBTEIgaG9zdC1iYXNlZCByb3V0aW5nLlxuICAgKi9cbiAgaG9zdD86IHN0cmluZztcblxuICAvKipcbiAgICogUHJpb3JpdHkgZm9yIHRoaXMgcm91dGluZyBydWxlICgxLTUwMDAwKS5cbiAgICogTG93ZXIgbnVtYmVyID0gaGlnaGVyIHByaW9yaXR5LlxuICAgKiBBdXRvLWFzc2lnbmVkIGlmIG9taXR0ZWQuXG4gICAqL1xuICBwcmlvcml0eT86IG51bWJlcjtcblxuICAvKipcbiAgICogSGVhbHRoIGNoZWNrIHBhdGggZm9yIHRoaXMgc2VydmljZSdzIHRhcmdldCBncm91cC5cbiAgICogRGVmYXVsdDogXCIvXCJcbiAgICovXG4gIGhlYWx0aENoZWNrUGF0aD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciBhIHNlcnZpY2UgaW4gYW4gRUNTIGNsdXN0ZXIuXG4gKiBFYWNoIHNlcnZpY2UgZ2V0cyBpdHMgb3duIHRhc2sgZGVmaW5pdGlvbiwgc2NhbGluZyBjb25maWcsIGFuZCB0YXJnZXQgZ3JvdXAuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNpbXBsZSBzZXJ2aWNlXG4gKiB7IG5hbWU6IFwiYXBpXCIsIGNvbnRhaW5lcnM6IFt7IHBvcnQ6IDMwMDAgfV0gfVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBTZXJ2aWNlIHdpdGggcm91dGluZyAoZm9yIG11bHRpLXNlcnZpY2UgY2x1c3RlcnMpXG4gKiB7IG5hbWU6IFwidXNlcnNcIiwgY29udGFpbmVyczogW3sgcG9ydDogMzAwMCB9XSwgcm91dGluZzogeyBwYXRoOiBcIi91c2Vycy8qXCIsIHByaW9yaXR5OiAxMDAgfSB9XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNlcnZpY2Ugd2l0aCBtdWx0aXBsZSByb3V0aW5nIHJ1bGVzIChzYW1lIHRhcmdldCBncm91cClcbiAqIHsgbmFtZTogXCJ3ZWJcIiwgY29udGFpbmVyczogW3sgcG9ydDogMzAwMCB9XSwgcm91dGluZzogW1xuICogICB7IHBhdGg6IFwiL2FwaS92Mi8qXCIsIHByaW9yaXR5OiA1MCB9LFxuICogICB7IHBhdGg6IFwiLypcIiwgcHJpb3JpdHk6IDIwMCB9LFxuICogXX1cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gU2VydmljZSB3aXRoIHNpZGVjYXJzXG4gKiB7XG4gKiAgIG5hbWU6IFwiYXBpXCIsXG4gKiAgIGNvbnRhaW5lcnM6IFtcbiAqICAgICB7IG5hbWU6IFwiYXBwXCIsIHBvcnQ6IDMwMDAgfSxcbiAqICAgICB7IG5hbWU6IFwiZGF0YWRvZ1wiLCBpbWFnZTogXCJkYXRhZG9nL2FnZW50XCIgfVxuICogICBdXG4gKiB9XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWNzU2VydmljZUNvbmZpZyB7XG4gIC8qKiBTZXJ2aWNlIG5hbWUgKHVuaXF1ZSB3aXRoaW4gY2x1c3RlcikgKi9cbiAgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDb250YWluZXIgaW1hZ2UgZm9yIHRoaXMgc2VydmljZSAoYXBwbGllcyB0byBmaXJzdCBjb250YWluZXIgd2l0aG91dCBleHBsaWNpdCBpbWFnZSkuXG4gICAqIC0gT21pdDogVXNlcyBhcHAncyBkZWZhdWx0IEVDUiByZXBvc2l0b3J5XG4gICAqIC0gc3RyaW5nOiBFQ1IgcmVwb3NpdG9yeSBuYW1lIG9yIHB1YmxpYyBpbWFnZSBVUkxcbiAgICogLSBSZXBvc2l0b3J5OiBDREsgRUNSIFJlcG9zaXRvcnkgY29uc3RydWN0XG4gICAqL1xuICBpbWFnZT86IHN0cmluZyB8IFJlcG9zaXRvcnk7XG5cbiAgLyoqXG4gICAqIENvbnRhaW5lciBjb25maWd1cmF0aW9uKHMpIGZvciB0aGlzIHNlcnZpY2UuXG4gICAqIEZvciBzaW5nbGUtY29udGFpbmVyIHNlcnZpY2VzLCBjb250YWluZXIgbmFtZSBpcyBvcHRpb25hbCBhbmQgYXV0by1nZW5lcmF0ZWQuXG4gICAqIEZvciBtdWx0aS1jb250YWluZXIgc2VydmljZXMsIHRoZSBmaXJzdCBjb250YWluZXIgd2l0aCBhIHBvcnQgaXMgdGhlIHByaW1hcnkgY29udGFpbmVyLlxuICAgKi9cbiAgY29udGFpbmVycz86IEVjc0NvbnRhaW5lckNvbmZpZ1tdO1xuXG4gIC8qKlxuICAgKiBSb3V0aW5nIHJ1bGVzIGZvciB0aGlzIHNlcnZpY2Ugb24gdGhlIGNsdXN0ZXIncyBBTEIuXG4gICAqIFJlcXVpcmVkIHdoZW4gY2x1c3RlciBoYXMgbXVsdGlwbGUgc2VydmljZXMgd2l0aCBwb3J0cy5cbiAgICogT3B0aW9uYWwgZm9yIHNpbmdsZSBzZXJ2aWNlIChnZXRzIC8qIGF1dG9tYXRpY2FsbHkpLlxuICAgKiBDYW4gYmUgYSBzaW5nbGUgcnVsZSBvciBhbiBhcnJheSBvZiBydWxlcyBwb2ludGluZyB0byB0aGUgc2FtZSB0YXJnZXQgZ3JvdXAuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIE11bHRpcGxlIHJvdXRlcyBmb3IgdGhlIHNhbWUgc2VydmljZVxuICAgKiByb3V0aW5nOiBbXG4gICAqICAgeyBwYXRoOiBcIi9hcGkvdjIvKlwiLCBwcmlvcml0eTogNTAgfSxcbiAgICogICB7IHBhdGg6IFwiLypcIiwgcHJpb3JpdHk6IDIwMCB9LFxuICAgKiBdXG4gICAqL1xuICByb3V0aW5nPzogRWNzUm91dGluZ0NvbmZpZyB8IEVjc1JvdXRpbmdDb25maWdbXTtcblxuICAvKiogQ1BVIHVuaXRzIGZvciB0aGlzIHNlcnZpY2UncyB0YXNrcyAoMjU2LTQwOTYpICovXG4gIGNwdT86IG51bWJlcjtcblxuICAvKiogTWVtb3J5IGluIE1pQiBmb3IgdGhpcyBzZXJ2aWNlJ3MgdGFza3MgKDUxMi0zMDcyMCkgKi9cbiAgbWVtb3J5TGltaXRNaUI/OiBudW1iZXI7XG5cbiAgLyoqIERlc2lyZWQgbnVtYmVyIG9mIHRhc2tzLiBEZWZhdWx0OiAyICovXG4gIGRlc2lyZWRDb3VudD86IG51bWJlcjtcblxuICAvKipcbiAgICogU2NhbGluZyBjb25maWd1cmF0aW9uLlxuICAgKiAtIE9taXQ6IGVuYWJsZWQgd2l0aCBkZWZhdWx0c1xuICAgKiAtIGZhbHNlOiBkaXNhYmxlZFxuICAgKi9cbiAgc2NhbGluZz86IEVjc1NjYWxpbmdDb25maWcgfCBmYWxzZTtcblxuICAvKipcbiAgICogUGF0aCB0byBEb2NrZXJmaWxlIGZvciBidWlsZGluZyB0aGlzIHNlcnZpY2UncyBpbWFnZS5cbiAgICogTWV0YWRhdGEgZm9yIENMSSBidWlsZCBwcm9jZXNzLCBub3QgdXNlZCBkdXJpbmcgQ0RLIHN5bnRoZXNpcy5cbiAgICovXG4gIGRvY2tlcmZpbGVQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEb2NrZXIgYnVpbGQgdGFyZ2V0IHN0YWdlIGZvciBtdWx0aS1zdGFnZSBEb2NrZXJmaWxlcy5cbiAgICogV2hlbiBzcGVjaWZpZWQsIHRoZSBDTEkgYnVpbGRzIHdpdGggYC0tdGFyZ2V0IDxkb2NrZXJUYXJnZXQ+YC5cbiAgICogVGhlIGltYWdlIHRhZyBzdWZmaXggaXMgYWxzbyB1cGRhdGVkOiBgPHNlcnZpY2U+LTx0YXJnZXQ+LWxhdGVzdGAuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIERvY2tlcmZpbGU6IEZST00gbm9kZSBBUyBiYXNlIC4uLiBGUk9NIGJhc2UgQVMgYXBpIC4uLiBGUk9NIGJhc2UgQVMgd29ya2VyXG4gICAqIHsgbmFtZTogXCJhcGlcIiwgZG9ja2VyVGFyZ2V0OiBcImFwaVwiIH0gICAvLyBidWlsZHM6IG15YXBwLWFwaS1hcGktbGF0ZXN0XG4gICAqIHsgbmFtZTogXCJ3b3JrZXJcIiwgZG9ja2VyVGFyZ2V0OiBcIndvcmtlclwiIH0gIC8vIGJ1aWxkczogbXlhcHAtd29ya2VyLXdvcmtlci1sYXRlc3RcbiAgICovXG4gIGRvY2tlclRhcmdldD86IHN0cmluZztcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBpbmxpbmUgcG9saWNpZXMgZm9yIHRoaXMgc2VydmljZSdzIHRhc2sgcm9sZS5cbiAgICogQWRkZWQgb24gdG9wIG9mIHRoZSBkZWZhdWx0IEVDUyBFeGVjIHBlcm1pc3Npb25zLlxuICAgKiBVc2UgZm9yIHNlcnZpY2Utc3BlY2lmaWMgQVdTIHBlcm1pc3Npb25zIChTMywgRHluYW1vREIsIFNRUywgZXRjLikuXG4gICAqL1xuICB0YXNrUm9sZUlubGluZVBvbGljaWVzPzogUmVjb3JkPHN0cmluZywgUG9saWN5RG9jdW1lbnQ+O1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIG1hbmFnZWQgcG9saWNpZXMgZm9yIHRoaXMgc2VydmljZSdzIHRhc2sgcm9sZS5cbiAgICogQWRkZWQgb24gdG9wIG9mIHRoZSBkZWZhdWx0IEVDUyBFeGVjIHBlcm1pc3Npb25zLlxuICAgKi9cbiAgdGFza1JvbGVNYW5hZ2VkUG9saWNpZXM/OiBJTWFuYWdlZFBvbGljeVtdO1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZXMgdGhpcyBzZXJ2aWNlIG5lZWRzIHRvIGNvbm5lY3QgdG8gKGUuZy4sIGRhdGFiYXNlcywgUzMgYnVja2V0cywgU1FTIHF1ZXVlcykuXG4gICAqIENyZWF0ZXMgc2VjdXJpdHkgZ3JvdXAgcnVsZXMgZm9yIElDb25uZWN0YWJsZSByZXNvdXJjZXMgYW5kIElBTSBncmFudHMgZm9yIElBTSByZXNvdXJjZXMuXG4gICAqIEZvbGxvd3MgbGVhc3QtcHJpdmlsZWdlIC0gb25seSB0aGlzIHNlcnZpY2UgZ2V0cyBhY2Nlc3MsIG5vdCBhbGwgc2VydmljZXMgaW4gdGhlIGNsdXN0ZXIuXG4gICAqXG4gICAqIFN1cHBvcnRzOlxuICAgKiAtIElDb25uZWN0YWJsZTogU2VjdXJpdHkgZ3JvdXAgcmVzb3VyY2VzIChSRFMsIEVDUywgZXRjLilcbiAgICogLSBJU3RvcmFnZUNvbm5lY3RvcjogUzMgYnVja2V0cyAoSUFNIGdyYW50cylcbiAgICogLSBJRHluYW1vREJDb25uZWN0b3I6IER5bmFtb0RCIHRhYmxlcyAoSUFNIGdyYW50cylcbiAgICogLSBJUXVldWVDb25uZWN0b3I6IFNRUyBxdWV1ZXMgKElBTSBncmFudHMpXG4gICAqIC0gQ29ubmVjdGlvbkNvbmZpZzogRXhwbGljaXQgYWNjZXNzIGxldmVsIGNvbmZpZ3VyYXRpb25cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gU2ltcGxlIGNvbm5lY3Rpb25zIChkZWZhdWx0IHBlcm1pc3Npb25zKVxuICAgKiBjb25uZWN0aW9uczogW2RhdGFiYXNlLCBidWNrZXQsIGNhY2hlLCBxdWV1ZV1cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gRXhwbGljaXQgYWNjZXNzIGxldmVsc1xuICAgKiBjb25uZWN0aW9uczogW1xuICAgKiAgIGRhdGFiYXNlLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNlY3VyaXR5IGdyb3VwIChSRFMpXG4gICAqICAgeyByZXNvdXJjZTogY2FjaGUsIGFjY2VzczogXCJyZWFkXCIgfSwgICAvLyBSZWFkLW9ubHkgRHluYW1vREJcbiAgICogICB7IHJlc291cmNlOiBidWNrZXQsIGFjY2VzczogXCJ3cml0ZVwiIH0sIC8vIFdyaXRlLW9ubHkgUzNcbiAgICogICB7IHJlc291cmNlOiBxdWV1ZSwgYWNjZXNzOiBcImNvbnN1bWVcIiB9IC8vIENvbnN1bWUtb25seSBTUVNcbiAgICogXVxuICAgKi9cbiAgY29ubmVjdGlvbnM/OiBDb25uZWN0aW9uU3BlY1tdO1xuXG4gIC8qKlxuICAgKiBDYXBhY2l0eSBwcm92aWRlciBmb3IgdGhpcyBzZXJ2aWNlLiBSRVFVSVJFRC5cbiAgICogRWFjaCBzZXJ2aWNlIHNwZWNpZmllcyBpdHMgb3duIGNhcGFjaXR5IHByb3ZpZGVyLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBNaXhlZCBGQVJHQVRFIGFuZCBFQzIgc2VydmljZXMgaW4gc2FtZSBjbHVzdGVyXG4gICAqIHtcbiAgICogICBzZXJ2aWNlczogW1xuICAgKiAgICAgeyBuYW1lOiBcImFwaVwiLCBjYXBhY2l0eVByb3ZpZGVyOiBcIkZBUkdBVEVcIiB9LFxuICAgKiAgICAgeyBuYW1lOiBcIndvcmtlclwiLCBjYXBhY2l0eVByb3ZpZGVyOiBcIkVDMlwiLCBlYzJDb25maWc6IHsgaW5zdGFuY2VUeXBlOiBcInQ0Zy5taWNyb1wiIH0gfVxuICAgKiAgIF1cbiAgICogfVxuICAgKi9cbiAgY2FwYWNpdHlQcm92aWRlcjogRWNzQ2FwYWNpdHlQcm92aWRlcjtcblxuICAvKipcbiAgICogRUMyIGNhcGFjaXR5IGNvbmZpZ3VyYXRpb24gZm9yIHRoaXMgc2VydmljZS5cbiAgICogT25seSB1c2VkIHdoZW4gc2VydmljZSBjYXBhY2l0eVByb3ZpZGVyIGlzIFwiRUMyXCIuXG4gICAqIFNlcnZpY2VzIHdpdGggbWF0Y2hpbmcgZWMyQ29uZmlnIHNoYXJlIGFuIEFTRyBmb3IgZWZmaWNpZW5jeS5cbiAgICovXG4gIGVjMkNvbmZpZz86IEVjMkNhcGFjaXR5Q29uZmlnO1xuXG4gIC8qKlxuICAgKiBTU00gUGFyYW1ldGVyIFN0b3JlIHBhdGggZm9yIHNlY3JldHMuXG4gICAqIElmIG5vdCBzcGVjaWZpZWQsIHNlY3JldHMgYXJlIGZldGNoZWQgZnJvbSAvPGFwcD4vPGNsdXN0ZXI+LzxzZXJ2aWNlPi5cbiAgICogVXNlIHRoaXMgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgY29udmVudGlvbi5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gT3ZlcnJpZGUgZGVmYXVsdCBwYXRoXG4gICAqIHNzbVNlY3JldHNQYXRoOiBcIi9jdXN0b20vcGF0aC90by9zZWNyZXRzXCJcbiAgICovXG4gIHNzbVNlY3JldHNQYXRoPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEVDUyBjb21wdXRlIGNvbmZpZ3VyYXRpb24uXG4gKiBDcmVhdGVzIGFuIEVDUyBjbHVzdGVyIHdpdGggb25lIG9yIG1vcmUgc2VydmljZXMgc2hhcmluZyBhIGxvYWQgYmFsYW5jZXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNpbmdsZSBzZXJ2aWNlXG4gKiBhcHAuYWRkQ29tcHV0ZShDb21wdXRlRmFjdG9yeS5idWlsZChcIldlYkFwcFwiLCB7XG4gKiAgIHR5cGU6IFwiZWNzXCIsXG4gKiAgIGNsdXN0ZXI6IHsgZG9tYWluOiBcImFwcC5leGFtcGxlLmNvbVwiIH0sXG4gKiAgIHNlcnZpY2VzOiBbeyBuYW1lOiBcIndlYlwiLCBjb250YWluZXJzOiBbeyBwb3J0OiAzMDAwIH1dIH1dXG4gKiB9KSk7XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIE11bHRpLXNlcnZpY2UgY2x1c3RlciB3aXRoIHJvdXRpbmdcbiAqIGFwcC5hZGRDb21wdXRlKENvbXB1dGVGYWN0b3J5LmJ1aWxkKFwiQXBpQ2x1c3RlclwiLCB7XG4gKiAgIHR5cGU6IFwiZWNzXCIsXG4gKiAgIGNsdXN0ZXI6IHsgZG9tYWluOiBcImFwaS5leGFtcGxlLmNvbVwiIH0sXG4gKiAgIHNlcnZpY2VzOiBbXG4gKiAgICAgeyBuYW1lOiBcInVzZXJzXCIsIGNvbnRhaW5lcnM6IFt7IHBvcnQ6IDMwMDAgfV0sIHJvdXRpbmc6IHsgcGF0aDogXCIvdXNlcnMvKlwiIH0gfSxcbiAqICAgICB7IG5hbWU6IFwib3JkZXJzXCIsIGNvbnRhaW5lcnM6IFt7IHBvcnQ6IDMwMDEgfV0sIHJvdXRpbmc6IHsgcGF0aDogXCIvb3JkZXJzLypcIiB9IH1cbiAqICAgXVxuICogfSkpO1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBJbnRlcm5hbCB3b3JrZXJzIChubyBBTEIpXG4gKiBhcHAuYWRkQ29tcHV0ZShDb21wdXRlRmFjdG9yeS5idWlsZChcIldvcmtlcnNcIiwge1xuICogICB0eXBlOiBcImVjc1wiLFxuICogICBjbHVzdGVyOiB7IGxvYWRCYWxhbmNlcjogZmFsc2UgfSxcbiAqICAgc2VydmljZXM6IFt7IG5hbWU6IFwicHJvY2Vzc29yXCIgfSwgeyBuYW1lOiBcImVtYWlsZXJcIiB9XVxuICogfSkpO1xuICovXG5leHBvcnQgaW50ZXJmYWNlIEVjc0NvbXB1dGVQcm9wcyB7XG4gIHR5cGU6IFwiZWNzXCI7XG4gIHZwYz86IElWcGM7XG5cbiAgLyoqXG4gICAqIEFwcGxpY2F0aW9uIG5hbWUgZm9yIFNTTSBzZWNyZXRzIG5hbWVzcGFjZS5cbiAgICogV2hlbiBjb250YWluZXJzIHVzZSBzZWNyZXRzLCB0aGUgcGF0aCBpcyBkZXJpdmVkIGFzOiAvPGFwcE5hbWU+LzxjbHVzdGVyTmFtZT4vPHNlcnZpY2VOYW1lPlxuICAgKiBBdXRvLWRlcml2ZWQgZnJvbSBBcHAuZ2V0TmFtZSgpIGlmIG5vdCBzcGVjaWZpZWQuXG4gICAqL1xuICBhcHBOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDbHVzdGVyIGNvbmZpZ3VyYXRpb24uXG4gICAqIENvbnRyb2xzIHRoZSBzaGFyZWQgQUxCIGZvciBhbGwgc2VydmljZXMgaW4gdGhpcyBjbHVzdGVyLlxuICAgKiAtIE9taXQ6IEFMQiBjcmVhdGVkIHdpdGggZGVmYXVsdCBzZXR0aW5nc1xuICAgKiAtIGB7IGRvbWFpbjogXCIuLi5cIiB9YDogQUxCIHdpdGggSFRUUFMgKyBETlNcbiAgICogLSBgeyBsb2FkQmFsYW5jZXI6IGZhbHNlIH1gOiBObyBBTEIgKGludGVybmFsIHdvcmtlcnMpXG4gICAqL1xuICBjbHVzdGVyPzogRWNzQ2x1c3RlckNvbmZpZztcblxuICAvKipcbiAgICogU2VydmljZXMgaW4gdGhpcyBjbHVzdGVyLlxuICAgKiBFYWNoIHNlcnZpY2UgZ2V0cyBpdHMgb3duIHRhc2sgZGVmaW5pdGlvbiwgc2NhbGluZywgYW5kIHRhcmdldCBncm91cC5cbiAgICogRWFjaCBzZXJ2aWNlIE1VU1Qgc3BlY2lmeSBpdHMgb3duIGNhcGFjaXR5UHJvdmlkZXIuXG4gICAqIEFsbCBzZXJ2aWNlcyBzaGFyZSB0aGUgY2x1c3RlcidzIEFMQiAodW5sZXNzIGRpc2FibGVkKS5cbiAgICovXG4gIHNlcnZpY2VzOiBFY3NTZXJ2aWNlQ29uZmlnW107XG5cbiAgLyoqXG4gICAqIEVDUiByZXBvc2l0b3J5IGZvciBhbGwgc2VydmljZXMgKGRlZmF1bHQgaW1hZ2UpLlxuICAgKiBJbmRpdmlkdWFsIHNlcnZpY2VzIGNhbiBvdmVycmlkZSB3aXRoIHRoZWlyIG93biBgaW1hZ2VgIHByb3BlcnR5LlxuICAgKi9cbiAgZWNyUmVwb3NpdG9yeT86IFJlcG9zaXRvcnkgfCBSZXBvc2l0b3J5SW1hZ2U7XG5cbiAgLyoqXG4gICAqIFBhdGggdG8gRG9ja2VyZmlsZSBmb3IgYnVpbGRpbmcgY3VzdG9tIGltYWdlLlxuICAgKiBOb3RlOiBUaGlzIGlzIG1ldGFkYXRhIGZvciB0aGUgQ0xJIGJ1aWxkIHByb2Nlc3MsXG4gICAqIG5vdCB1c2VkIGR1cmluZyBDREsgc3ludGhlc2lzLlxuICAgKi9cbiAgZG9ja2VyZmlsZVBhdGg/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIEVDUy1zcGVjaWZpYyBwcm9wcy5cbiAqIEV4dHJhY3RlZCBmb3IgY2xhcml0eSBhbmQgZGV0YWlsIHBhcml0eSB3aXRoIGRhdGFiYXNlL25ldHdvcmsgcGF0dGVybnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUVjc1Byb3BzKHByb3BzOiBFY3NDb21wdXRlUHJvcHMpOiB2b2lkIHtcbiAgLy8gVmFsaWRhdGUgc2VydmljZXMgYXJyYXkgZXhpc3RzIGFuZCBpcyBub3QgZW1wdHlcbiAgaWYgKCFwcm9wcy5zZXJ2aWNlcyB8fCBwcm9wcy5zZXJ2aWNlcy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcIkF0IGxlYXN0IG9uZSBzZXJ2aWNlIG11c3QgYmUgc3BlY2lmaWVkIGluICdzZXJ2aWNlcycgYXJyYXkuXCJcbiAgICApO1xuICB9XG5cbiAgLy8gVmFsaWRhdGUgdW5pcXVlIHNlcnZpY2UgbmFtZXNcbiAgY29uc3Qgc2VydmljZU5hbWVzID0gcHJvcHMuc2VydmljZXMubWFwKChzKSA9PiBzLm5hbWUpO1xuICBjb25zdCBkdXBsaWNhdGVOYW1lcyA9IHNlcnZpY2VOYW1lcy5maWx0ZXIoXG4gICAgKG5hbWUsIGluZGV4KSA9PiBzZXJ2aWNlTmFtZXMuaW5kZXhPZihuYW1lKSAhPT0gaW5kZXhcbiAgKTtcbiAgaWYgKGR1cGxpY2F0ZU5hbWVzLmxlbmd0aCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRHVwbGljYXRlIHNlcnZpY2UgbmFtZXM6ICR7Wy4uLm5ldyBTZXQoZHVwbGljYXRlTmFtZXMpXS5qb2luKFwiLCBcIil9YFxuICAgICk7XG4gIH1cblxuICAvLyBWYWxpZGF0ZSBzZXJ2aWNlIG5hbWUgZm9ybWF0XG4gIGNvbnN0IGludmFsaWROYW1lcyA9IHByb3BzLnNlcnZpY2VzLmZpbHRlcihcbiAgICAocykgPT4gIS9eW2EtekEtWl1bYS16QS1aMC05LV0qJC8udGVzdChzLm5hbWUpXG4gICk7XG4gIGlmIChpbnZhbGlkTmFtZXMubGVuZ3RoID4gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBJbnZhbGlkIHNlcnZpY2UgbmFtZXM6ICR7aW52YWxpZE5hbWVzLm1hcCgocykgPT4gcy5uYW1lKS5qb2luKFwiLCBcIil9LiBgICtcbiAgICAgICAgXCJTZXJ2aWNlIG5hbWVzIG11c3Qgc3RhcnQgd2l0aCBhIGxldHRlciBhbmQgY29udGFpbiBvbmx5IGxldHRlcnMsIG51bWJlcnMsIGFuZCBoeXBoZW5zLlwiXG4gICAgKTtcbiAgfVxuXG4gIC8vIFZhbGlkYXRlIHJvdXRpbmcgd2hlbiBtdWx0aXBsZSBzZXJ2aWNlcyBoYXZlIHBvcnRzXG4gIGNvbnN0IHNlcnZpY2VzV2l0aFBvcnRzID0gcHJvcHMuc2VydmljZXMuZmlsdGVyKChzKSA9PlxuICAgIHMuY29udGFpbmVycz8uc29tZSgoYykgPT4gYy5wb3J0KVxuICApO1xuXG4gIGlmIChzZXJ2aWNlc1dpdGhQb3J0cy5sZW5ndGggPiAxKSB7XG4gICAgY29uc3QgbWlzc2luZ1JvdXRpbmcgPSBzZXJ2aWNlc1dpdGhQb3J0cy5maWx0ZXIoKHMpID0+IHtcbiAgICAgIGNvbnN0IHJ1bGVzID0gQXJyYXkuaXNBcnJheShzLnJvdXRpbmcpXG4gICAgICAgID8gcy5yb3V0aW5nXG4gICAgICAgIDogcy5yb3V0aW5nXG4gICAgICAgICAgPyBbcy5yb3V0aW5nXVxuICAgICAgICAgIDogW107XG4gICAgICByZXR1cm4gIXJ1bGVzLnNvbWUoKHIpID0+IHIucGF0aCB8fCByLmhvc3QpO1xuICAgIH0pO1xuICAgIGlmIChtaXNzaW5nUm91dGluZy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBTZXJ2aWNlcyB3aXRoIHBvcnRzIHJlcXVpcmUgcm91dGluZyBjb25maWcgd2hlbiBjbHVzdGVyIGhhcyBtdWx0aXBsZSBzZXJ2aWNlczogYCArXG4gICAgICAgICAgYCR7bWlzc2luZ1JvdXRpbmcubWFwKChzKSA9PiBzLm5hbWUpLmpvaW4oXCIsIFwiKX0uIGAgK1xuICAgICAgICAgIFwiQWRkIHJvdXRpbmc6IHsgcGF0aDogJy8uLi4nIH0gb3Igcm91dGluZzogeyBob3N0OiAnLi4uJyB9IHRvIGVhY2ggc2VydmljZS5cIlxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBWYWxpZGF0ZSBlYWNoIHNlcnZpY2UncyBjb250YWluZXJzXG4gIGZvciAoY29uc3Qgc2VydmljZSBvZiBwcm9wcy5zZXJ2aWNlcykge1xuICAgIGlmIChzZXJ2aWNlLmNvbnRhaW5lcnMgJiYgc2VydmljZS5jb250YWluZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIENoZWNrIGZvciBkdXBsaWNhdGUgY29udGFpbmVyIG5hbWVzIHdpdGhpbiBzZXJ2aWNlIChvbmx5IG5hbWVkIGNvbnRhaW5lcnMpXG4gICAgICBjb25zdCBjb250YWluZXJOYW1lcyA9IHNlcnZpY2UuY29udGFpbmVyc1xuICAgICAgICAuZmlsdGVyKChjKSA9PiBjLm5hbWUpXG4gICAgICAgIC5tYXAoKGMpID0+IGMubmFtZSk7XG4gICAgICBjb25zdCBkdXBsaWNhdGVDb250YWluZXJOYW1lcyA9IGNvbnRhaW5lck5hbWVzLmZpbHRlcihcbiAgICAgICAgKG5hbWUsIGluZGV4KSA9PiBjb250YWluZXJOYW1lcy5pbmRleE9mKG5hbWUpICE9PSBpbmRleFxuICAgICAgKTtcbiAgICAgIGlmIChkdXBsaWNhdGVDb250YWluZXJOYW1lcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgU2VydmljZSAnJHtzZXJ2aWNlLm5hbWV9JzogRHVwbGljYXRlIGNvbnRhaW5lciBuYW1lczogYCArXG4gICAgICAgICAgICBgJHtbLi4ubmV3IFNldChkdXBsaWNhdGVDb250YWluZXJOYW1lcyldLmpvaW4oXCIsIFwiKX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNlcnZpY2UuY2FwYWNpdHlQcm92aWRlciA9PT0gXCJFQzJcIiAmJiAhc2VydmljZS5lYzJDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFNlcnZpY2UgJyR7c2VydmljZS5uYW1lfScgdXNlcyBFQzIgY2FwYWNpdHkgcHJvdmlkZXIgYnV0IG5vIGVjMkNvbmZpZyBpcyBkZWZpbmVkLiBgICtcbiAgICAgICAgICBcIlByb3ZpZGUgZWMyQ29uZmlnIG9uIHRoZSBzZXJ2aWNlLlwiXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFdhcm4gaWYgc2VydmljZSBlYzJDb25maWcgaXMgZGVmaW5lZCBidXQgY2FwYWNpdHlQcm92aWRlciBpcyBub3QgRUMyXG4gICAgaWYgKHNlcnZpY2UuZWMyQ29uZmlnICYmIHNlcnZpY2UuY2FwYWNpdHlQcm92aWRlciAhPT0gXCJFQzJcIikge1xuICAgICAgRmphbGxMb2dnZXIud2FybihcbiAgICAgICAgYFNlcnZpY2UgJyR7c2VydmljZS5uYW1lfScgaGFzIGVjMkNvbmZpZyBidXQgY2FwYWNpdHlQcm92aWRlciBpcyBub3QgJ0VDMicuIGAgK1xuICAgICAgICAgIFwiVGhlIGVjMkNvbmZpZyB3aWxsIGJlIGlnbm9yZWQgdW5sZXNzIGNhcGFjaXR5UHJvdmlkZXIgaXMgc2V0IHRvICdFQzInLlwiXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEJ1aWxkIGNvbnRhaW5lciBjb25maWd1cmF0aW9ucyBmb3IgYW4gRUNTIHNlcnZpY2UuXG4gKiBDb252ZXJ0cyB1c2VyLWZhY2luZyBFY3NDb250YWluZXJDb25maWcgdG8gaW50ZXJuYWwgRWNzQ2x1c3RlclByb3BzIGZvcm1hdC5cbiAqIEBpbnRlcm5hbCBFeHBvcnRlZCBmb3IgdGVzdGluZyBvbmx5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZENvbnRhaW5lckNvbmZpZ3MoXG4gIHNlcnZpY2U6IEVjc1NlcnZpY2VDb25maWdcbik6IEVjc0NsdXN0ZXJQcm9wc1tcInNlcnZpY2VzXCJdW251bWJlcl1bXCJjb250YWluZXJzXCJdIHtcbiAgaWYgKHNlcnZpY2UuY29udGFpbmVycyAmJiBzZXJ2aWNlLmNvbnRhaW5lcnMubGVuZ3RoID4gMCkge1xuICAgIHJldHVybiBzZXJ2aWNlLmNvbnRhaW5lcnMubWFwKChjLCBpbmRleCkgPT4gKHtcbiAgICAgIG5hbWU6IGMubmFtZSB8fCBgJHtzZXJ2aWNlLm5hbWV9Q29udGFpbmVyJHtpbmRleCA+IDAgPyBpbmRleCA6IFwiXCJ9YCxcbiAgICAgIGltYWdlOiBjLmltYWdlLFxuICAgICAgcG9ydDogYy5wb3J0LFxuICAgICAgZW52aXJvbm1lbnQ6IGMuZW52aXJvbm1lbnQsXG4gICAgICBzZWNyZXRzOiBjLnNlY3JldHMsXG4gICAgICBzZWNyZXRzSW1wb3J0OiBjLnNlY3JldHNJbXBvcnQsXG4gICAgICBjb21tYW5kOiBjLmNvbW1hbmQsXG4gICAgICBlbnRyeVBvaW50OiBjLmVudHJ5UG9pbnQsXG4gICAgICBlc3NlbnRpYWw6IGMuZXNzZW50aWFsLFxuICAgICAgaGVhbHRoQ2hlY2s6IGMuaGVhbHRoQ2hlY2tcbiAgICB9KSk7XG4gIH1cbiAgLy8gRGVmYXVsdCBjb250YWluZXIgKG5vIHBvcnQgPSB3b3JrZXIpXG4gIHJldHVybiBbeyBuYW1lOiBgJHtzZXJ2aWNlLm5hbWV9Q29udGFpbmVyYCB9XTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlZCBzY2FsaW5nIGNvbmZpZ3VyYXRpb24gZm9yIGFuIEVDUyBzZXJ2aWNlLlxuICogQGludGVybmFsIEV4cG9ydGVkIGZvciB0ZXN0aW5nIG9ubHlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZFNjYWxpbmdDb25maWcge1xuICBzY2FsaW5nVHlwZTogU2NhbGluZ1R5cGUgfCB1bmRlZmluZWQ7XG4gIG1pbkNhcGFjaXR5OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIG1heENhcGFjaXR5OiBudW1iZXIgfCB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBzY2FsaW5nIGNvbmZpZ3VyYXRpb24gZnJvbSBzZXJ2aWNlIHByb3BzLlxuICogSGFuZGxlcyB0aGUgdGhyZWUgY2FzZXM6IGV4cGxpY2l0IGNvbmZpZywgZGlzYWJsZWQgKGZhbHNlKSwgb3IgZGVmYXVsdCAodW5kZWZpbmVkKS5cbiAqIEBpbnRlcm5hbCBFeHBvcnRlZCBmb3IgdGVzdGluZyBvbmx5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlU2NhbGluZ0NvbmZpZyhcbiAgc2NhbGluZzogRWNzU2NhbGluZ0NvbmZpZyB8IGZhbHNlIHwgdW5kZWZpbmVkXG4pOiBSZXNvbHZlZFNjYWxpbmdDb25maWcge1xuICBpZiAoc2NhbGluZyA9PT0gZmFsc2UpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc2NhbGluZ1R5cGU6IHVuZGVmaW5lZCxcbiAgICAgIG1pbkNhcGFjaXR5OiB1bmRlZmluZWQsXG4gICAgICBtYXhDYXBhY2l0eTogdW5kZWZpbmVkXG4gICAgfTtcbiAgfVxuICBpZiAoc2NhbGluZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNjYWxpbmdUeXBlOiBTY2FsaW5nVHlwZS5DUFUsXG4gICAgICBtaW5DYXBhY2l0eTogdW5kZWZpbmVkLFxuICAgICAgbWF4Q2FwYWNpdHk6IHVuZGVmaW5lZFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBzY2FsaW5nVHlwZTogc2NhbGluZy5zY2FsaW5nVHlwZSA/PyBTY2FsaW5nVHlwZS5DUFUsXG4gICAgbWluQ2FwYWNpdHk6IHNjYWxpbmcubWluQ2FwYWNpdHksXG4gICAgbWF4Q2FwYWNpdHk6IHNjYWxpbmcubWF4Q2FwYWNpdHlcbiAgfTtcbn1cblxuLyoqXG4gKiBFQ1MgY29tcHV0ZSB3cmFwcGVyIGltcGxlbWVudGluZyBJRWNzQ29tcHV0ZS5cbiAqIFByb3ZpZGVzIHR5cGUtc2FmZSBhY2Nlc3MgdG8gRUNTLXNwZWNpZmljIHJlc291cmNlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIEVjc0NvbXB1dGUgZXh0ZW5kcyBDb25zdHJ1Y3QgaW1wbGVtZW50cyBJRWNzQ29tcHV0ZSB7XG4gIHB1YmxpYyByZWFkb25seSBjb21wdXRlVHlwZSA9IFwiZWNzXCIgYXMgY29uc3Q7XG4gIHB1YmxpYyByZWFkb25seSBjb25uZWN0aW9uczogQ29ubmVjdGlvbnM7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBlY3NDbHVzdGVyOiBFY3NDbHVzdGVyO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBFY3NDb21wdXRlUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgLy8gVHJhbnNmb3JtIEVjc1NlcnZpY2VDb25maWdbXSB0byBFY3NTZXJ2aWNlUHJvcHNbXSBmb3IgRWNzQ2x1c3RlclxuICAgIGNvbnN0IHNlcnZpY2VzOiBFY3NDbHVzdGVyUHJvcHNbXCJzZXJ2aWNlc1wiXSA9IHByb3BzLnNlcnZpY2VzLm1hcChcbiAgICAgIChzZXJ2aWNlKSA9PiB7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lcnMgPSBidWlsZENvbnRhaW5lckNvbmZpZ3Moc2VydmljZSk7XG4gICAgICAgIGNvbnN0IHsgc2NhbGluZ1R5cGUsIG1pbkNhcGFjaXR5LCBtYXhDYXBhY2l0eSB9ID0gcmVzb2x2ZVNjYWxpbmdDb25maWcoXG4gICAgICAgICAgc2VydmljZS5zY2FsaW5nXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBuYW1lOiBzZXJ2aWNlLm5hbWUsXG4gICAgICAgICAgaW1hZ2U6IHNlcnZpY2UuaW1hZ2UsXG4gICAgICAgICAgY29udGFpbmVycyxcbiAgICAgICAgICBjcHU6IHNlcnZpY2UuY3B1LFxuICAgICAgICAgIG1lbW9yeUxpbWl0TWlCOiBzZXJ2aWNlLm1lbW9yeUxpbWl0TWlCLFxuICAgICAgICAgIGRlc2lyZWRDb3VudDogc2VydmljZS5kZXNpcmVkQ291bnQsXG4gICAgICAgICAgc2NhbGluZ1R5cGUsXG4gICAgICAgICAgbWluQ2FwYWNpdHksXG4gICAgICAgICAgbWF4Q2FwYWNpdHksXG4gICAgICAgICAgcm91dGluZzogc2VydmljZS5yb3V0aW5nLFxuICAgICAgICAgIHRhc2tSb2xlSW5saW5lUG9saWNpZXM6IHNlcnZpY2UudGFza1JvbGVJbmxpbmVQb2xpY2llcyxcbiAgICAgICAgICB0YXNrUm9sZU1hbmFnZWRQb2xpY2llczogc2VydmljZS50YXNrUm9sZU1hbmFnZWRQb2xpY2llcyxcbiAgICAgICAgICBjb25uZWN0aW9uczogc2VydmljZS5jb25uZWN0aW9ucyxcbiAgICAgICAgICBjYXBhY2l0eVByb3ZpZGVyOiBzZXJ2aWNlLmNhcGFjaXR5UHJvdmlkZXIsXG4gICAgICAgICAgZWMyQ29uZmlnOiBzZXJ2aWNlLmVjMkNvbmZpZyxcbiAgICAgICAgICBzc21TZWNyZXRzUGF0aDogc2VydmljZS5zc21TZWNyZXRzUGF0aCxcbiAgICAgICAgICBkb2NrZXJUYXJnZXQ6IHNlcnZpY2UuZG9ja2VyVGFyZ2V0XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgKTtcblxuICAgIC8vIEJ1aWxkIGNsdXN0ZXIgY29uZmlnXG4gICAgY29uc3QgY2x1c3RlcjogRWNzQ2x1c3RlclByb3BzW1wiY2x1c3RlclwiXSA9IHByb3BzLmNsdXN0ZXJcbiAgICAgID8ge1xuICAgICAgICAgIGRvbWFpbjogcHJvcHMuY2x1c3Rlci5kb21haW4sXG4gICAgICAgICAgbG9hZEJhbGFuY2VyOiBwcm9wcy5jbHVzdGVyLmxvYWRCYWxhbmNlcixcbiAgICAgICAgICBkaXJlY3RBY2Nlc3M6IHByb3BzLmNsdXN0ZXIuZGlyZWN0QWNjZXNzLFxuICAgICAgICAgIGRvbWFpbkNvbmZpZzogcHJvcHMuY2x1c3Rlci5kb21haW5Db25maWdcbiAgICAgICAgfVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBlY3NQcm9wczogRWNzQ2x1c3RlclByb3BzID0ge1xuICAgICAgY2x1c3Rlck5hbWU6IGlkLFxuICAgICAgYXBwTmFtZTogcHJvcHMuYXBwTmFtZSxcbiAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgZWNyUmVwb3NpdG9yeTogcHJvcHMuZWNyUmVwb3NpdG9yeSB8fCBDT01QVVRFX0RFRkFVTFRTLkVDUy5GQUxMQkFDS19JTUFHRSxcbiAgICAgIGNsdXN0ZXIsXG4gICAgICBzZXJ2aWNlc1xuICAgIH07XG5cbiAgICB0aGlzLmVjc0NsdXN0ZXIgPSBuZXcgRWNzQ2x1c3RlcihzY29wZSwgYCR7aWR9RWNzYCwgZWNzUHJvcHMpO1xuICAgIHRoaXMuY29ubmVjdGlvbnMgPSB0aGlzLmVjc0NsdXN0ZXIuY29ubmVjdGlvbnM7XG4gIH1cblxuICAvKiogR2V0IHRoZSBFQ1MgY2x1c3Rlci4gKi9cbiAgZ2V0Q2x1c3RlcigpOiBJQ2x1c3RlciB7XG4gICAgcmV0dXJuIHRoaXMuZWNzQ2x1c3Rlci5nZXRDbHVzdGVyKCk7XG4gIH1cblxuICAvKiogR2V0IHRoZSBBcHBsaWNhdGlvbiBMb2FkIEJhbGFuY2VyIGlmIG9uZSB3YXMgY3JlYXRlZC4gKi9cbiAgZ2V0TG9hZEJhbGFuY2VyKCk6IElBcHBsaWNhdGlvbkxvYWRCYWxhbmNlciB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZWNzQ2x1c3Rlci5nZXRMb2FkQmFsYW5jZXIoKTtcbiAgfVxuXG4gIC8qKiBHZXQgYSBzcGVjaWZpYyBzZXJ2aWNlIGJ5IG5hbWUuICovXG4gIGdldFNlcnZpY2UobmFtZTogc3RyaW5nKTogSUJhc2VTZXJ2aWNlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5lY3NDbHVzdGVyLmdldFNlcnZpY2UobmFtZSk7XG4gIH1cblxuICAvKiogR2V0IGFsbCBzZXJ2aWNlcyBpbiB0aGUgY2x1c3Rlci4gKi9cbiAgZ2V0QWxsU2VydmljZXMoKTogSUJhc2VTZXJ2aWNlW10ge1xuICAgIGNvbnN0IHNlcnZpY2VzTWFwID0gdGhpcy5lY3NDbHVzdGVyLmdldFNlcnZpY2VzKCk7XG4gICAgcmV0dXJuIEFycmF5LmZyb20oc2VydmljZXNNYXAudmFsdWVzKCkpO1xuICB9XG5cbiAgLyoqIEdldCB0aGUgc2VjdXJpdHkgZ3JvdXAgZm9yIHRoZSBjbHVzdGVyLiAqL1xuICBnZXRTZWN1cml0eUdyb3VwKCk6IElTZWN1cml0eUdyb3VwIHtcbiAgICAvLyBSZXR1cm4gdGhlIGZpcnN0IHNlY3VyaXR5IGdyb3VwIGZyb20gY29ubmVjdGlvbnNcbiAgICBjb25zdCBzZWN1cml0eUdyb3VwcyA9IHRoaXMuY29ubmVjdGlvbnMuc2VjdXJpdHlHcm91cHM7XG4gICAgaWYgKHNlY3VyaXR5R3JvdXBzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gc2VjdXJpdHkgZ3JvdXBzIGZvdW5kIGZvciBFQ1MgY2x1c3RlclwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlY3VyaXR5R3JvdXBzWzBdO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgQUxCIGxpc3RlbmVyIGlmIHRoaXMgaXMgYW4gRUNTIGNvbXB1dGUgd2l0aCBBTEIuXG4gICAqL1xuICBnZXRMaXN0ZW5lcigpOiBBcHBsaWNhdGlvbkxpc3RlbmVyIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5lY3NDbHVzdGVyLmdldExpc3RlbmVyKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSB1bmRlcmx5aW5nIEVDUyBjbHVzdGVyIGNvbnN0cnVjdC5cbiAgICovXG4gIGdldEVjc0NsdXN0ZXIoKTogRWNzQ2x1c3RlciB7XG4gICAgcmV0dXJuIHRoaXMuZWNzQ2x1c3RlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgZWNzOkV4ZWN1dGVDb21tYW5kIHBlcm1pc3Npb24gZm9yIEVDUyBzZXJ2aWNlcy5cbiAgICogVXNlcyB3aWxkY2FyZCByZXNvdXJjZSBiZWNhdXNlIGVjczpFeGVjdXRlQ29tbWFuZCB0YXJnZXRzIHRhc2sgQVJOc1xuICAgKiB3aGljaCBhcmUgbm90IGtub3duIHVudGlsIHJ1bnRpbWUgKHRhc2tzIGFyZSBlcGhlbWVyYWwpLlxuICAgKi9cbiAgZ3JhbnRFeGVjdXRlQ29tbWFuZChncmFudGVlOiBJR3JhbnRhYmxlKTogR3JhbnQge1xuICAgIHJldHVybiBHcmFudC5hZGRUb1ByaW5jaXBhbCh7XG4gICAgICBncmFudGVlLFxuICAgICAgYWN0aW9uczogW1wiZWNzOkV4ZWN1dGVDb21tYW5kXCJdLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbXCIqXCJdXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,220 @@
1
+ import { Code, Runtime, type Architecture, type FunctionUrlAuthType, type FunctionUrlCorsOptions, type IFunction, type InvokeMode } from "aws-cdk-lib/aws-lambda";
2
+ import { type PolicyStatement, type IGrantable, type Grant } from "aws-cdk-lib/aws-iam";
3
+ import { Connections, type IVpc, type ISecurityGroup } from "aws-cdk-lib/aws-ec2";
4
+ import { Repository } from "aws-cdk-lib/aws-ecr";
5
+ import { type RepositoryImage } from "aws-cdk-lib/aws-ecs";
6
+ import { Construct } from "constructs";
7
+ import { type ILambdaCompute } from "./interfaces/compute.js";
8
+ import { type ConnectionSpec } from "./interfaces/connector.js";
9
+ import { LambdaFunction } from "../../resources/aws/compute/lambda";
10
+ import { type SecretImport } from "../../resources/aws/secrets";
11
+ export { Architecture, HttpMethod, InvokeMode, type FunctionUrlCorsOptions } from "aws-cdk-lib/aws-lambda";
12
+ /**
13
+ * Lambda function URL configuration.
14
+ * - Omit: disabled (default)
15
+ * - `{}`: enabled with IAM auth
16
+ * - `{ authType: "NONE", cors: {...} }`: public with CORS
17
+ * - `false`: explicitly disabled
18
+ */
19
+ export interface FunctionUrlConfig {
20
+ /** Authentication type. Default: AWS_IAM */
21
+ authType?: FunctionUrlAuthType;
22
+ /** CORS configuration */
23
+ cors?: FunctionUrlCorsOptions;
24
+ /** Invoke mode. Use RESPONSE_STREAM for Lambda streaming. Default: BUFFERED */
25
+ invokeMode?: InvokeMode;
26
+ }
27
+ /**
28
+ * Base Lambda configuration shared by both container and code deployments.
29
+ */
30
+ interface BaseLambdaProps {
31
+ type: "lambda";
32
+ vpc?: IVpc;
33
+ /** Timeout in seconds. Default: 3 */
34
+ timeout?: number;
35
+ /** Memory size in MB. Default: 128 */
36
+ memorySize?: number;
37
+ ephemeralStorageSize?: number;
38
+ /** CPU architecture. Default: x86_64. Use Architecture.ARM_64 for Graviton2. */
39
+ architecture?: Architecture;
40
+ /** Lambda function description */
41
+ description?: string;
42
+ /** IAM role description */
43
+ roleDescription?: string;
44
+ /** Inline IAM policy statements */
45
+ inlinePolicy?: PolicyStatement[];
46
+ /**
47
+ * Function URL configuration.
48
+ * - Omit: disabled (default)
49
+ * - `{}`: enabled with IAM auth
50
+ * - `{ authType: "NONE" }`: public access
51
+ * - `false`: explicitly disabled
52
+ */
53
+ functionUrl?: FunctionUrlConfig | false;
54
+ /** Environment variables */
55
+ environment?: Record<string, string>;
56
+ /**
57
+ * Secrets from AWS SSM Parameter Store.
58
+ * Array of secret names that will be fetched from the Lambda's SSM namespace.
59
+ * The namespace path is auto-determined as: /<appName>/lambda/<functionName>
60
+ *
61
+ * @example
62
+ * secrets: ["API_KEY", "STRIPE_SECRET"]
63
+ */
64
+ secrets?: string[];
65
+ /**
66
+ * SSM Parameter Store path for secrets.
67
+ * If secrets are defined, this path is used as the base path.
68
+ * If not specified, uses: /<appName>/lambda/<functionName>
69
+ *
70
+ * @example
71
+ * ssmSecretsPath: "/myapp/custom/path"
72
+ */
73
+ ssmSecretsPath?: string;
74
+ /**
75
+ * Secrets imported from other CDK resources (AWS Secrets Manager).
76
+ * Used for CDK-managed secrets like database credentials.
77
+ *
78
+ * @example
79
+ * secretsImport: {
80
+ * DATABASE_USERNAME: database.getCredentials().getImport("username"),
81
+ * DATABASE_PASSWORD: database.getCredentials().getImport("password")
82
+ * }
83
+ */
84
+ secretsImport?: Record<string, SecretImport>;
85
+ /**
86
+ * Application name for SSM secrets path derivation.
87
+ * Auto-derived from App instance when using ComputeFactory.
88
+ * Only specify for advanced use cases.
89
+ */
90
+ appName?: string;
91
+ /**
92
+ * Resources this Lambda needs to connect to (e.g., databases, S3 buckets, SQS queues).
93
+ * Creates security group rules for IConnectable resources and IAM grants for IAM resources.
94
+ *
95
+ * Supports:
96
+ * - IConnectable: Security group resources (RDS, ECS, etc.)
97
+ * - IStorageConnector: S3 buckets (IAM grants)
98
+ * - IDynamoDBConnector: DynamoDB tables (IAM grants)
99
+ * - IQueueConnector: SQS queues (IAM grants)
100
+ * - ConnectionConfig: Explicit access level configuration
101
+ *
102
+ * @example
103
+ * connections: [
104
+ * database,
105
+ * { resource: queue, access: "send" }
106
+ * ]
107
+ */
108
+ connections?: ConnectionSpec[];
109
+ /**
110
+ * EventBridge schedule expression for scheduled Lambda invocations.
111
+ * Uses cron or rate syntax: "rate(1 hour)" or "cron(0 12 * * ? *)".
112
+ */
113
+ scheduleExpression?: string;
114
+ }
115
+ /**
116
+ * Container-based Lambda using ECR image.
117
+ *
118
+ * Uses Docker image from ECR repository. Handler and runtime are
119
+ * automatically set to FROM_IMAGE.
120
+ *
121
+ * @example
122
+ * app.addCompute(ComputeFactory.build("ImageLambda", {
123
+ * type: "lambda",
124
+ * deployment: "container",
125
+ * ecrRepository: app.getDefaultContainerRegistry()
126
+ * }));
127
+ */
128
+ export interface ContainerLambdaProps extends BaseLambdaProps {
129
+ /** Container-based deployment using ECR image */
130
+ deployment: "container";
131
+ /** ECR repository containing the Lambda container image */
132
+ ecrRepository: Repository | RepositoryImage;
133
+ }
134
+ /**
135
+ * Code-based Lambda using inline code or S3.
136
+ *
137
+ * Uses traditional Lambda deployment with code, handler, and runtime.
138
+ *
139
+ * @example
140
+ * app.addCompute(ComputeFactory.build("CodeLambda", {
141
+ * type: "lambda",
142
+ * deployment: "code",
143
+ * code: Code.fromAsset("./lambda"),
144
+ * handler: "index.handler",
145
+ * runtime: Runtime.NODEJS_20_X
146
+ * }));
147
+ */
148
+ export interface CodeLambdaProps extends BaseLambdaProps {
149
+ /** Code-based deployment */
150
+ deployment: "code";
151
+ /** Lambda code (from asset, S3, or inline) */
152
+ code: Code;
153
+ /** Handler function. Default: "index.handler" */
154
+ handler?: string;
155
+ /** Lambda runtime. Default: NODEJS_22_X */
156
+ runtime?: Runtime;
157
+ }
158
+ /**
159
+ * Lambda compute configuration.
160
+ *
161
+ * Discriminated union ensuring type-safe Lambda configuration:
162
+ * - `deployment: "container"` requires `ecrRepository`
163
+ * - `deployment: "code"` requires `code` and allows `handler`/`runtime`
164
+ *
165
+ * @example
166
+ * // Container-based Lambda
167
+ * { type: "lambda", deployment: "container", ecrRepository: ecr }
168
+ *
169
+ * @example
170
+ * // Code-based Lambda
171
+ * { type: "lambda", deployment: "code", code: Code.fromAsset("./lambda") }
172
+ */
173
+ export type LambdaComputeProps = ContainerLambdaProps | CodeLambdaProps;
174
+ /**
175
+ * Resolved Lambda deployment configuration.
176
+ */
177
+ export interface ResolvedLambdaDeployment {
178
+ code: Code;
179
+ handler: string;
180
+ runtime: Runtime;
181
+ }
182
+ /**
183
+ * Resolve Lambda deployment configuration from props.
184
+ * Handles container vs code deployment types.
185
+ */
186
+ export declare function resolveLambdaDeployment(props: LambdaComputeProps): ResolvedLambdaDeployment;
187
+ /**
188
+ * Lambda compute wrapper implementing ILambdaCompute.
189
+ * Provides type-safe access to Lambda-specific resources.
190
+ */
191
+ export declare class LambdaCompute extends Construct implements ILambdaCompute {
192
+ readonly computeType: "lambda";
193
+ readonly connections: Connections;
194
+ private readonly lambdaFunction;
195
+ constructor(scope: Construct, id: string, props: LambdaComputeProps);
196
+ /**
197
+ * Get a Lambda function by name.
198
+ * Since we only have one function, name is ignored.
199
+ */
200
+ getFunction(_name?: string): IFunction | undefined;
201
+ /** Get all Lambda functions. */
202
+ getAllFunctions(): IFunction[];
203
+ /**
204
+ * Get the function URL for a Lambda function.
205
+ */
206
+ getFunctionUrl(_name?: string): string | undefined;
207
+ /**
208
+ * Grant invoke permissions to a grantee.
209
+ */
210
+ grantInvoke(grantee: IGrantable, _functionName?: string): Grant;
211
+ /**
212
+ * Get the security group for VPC-enabled Lambda functions.
213
+ * Returns undefined if the Lambda is not VPC-enabled.
214
+ */
215
+ getSecurityGroup(): ISecurityGroup | undefined;
216
+ /**
217
+ * Get the underlying Lambda function construct.
218
+ */
219
+ getLambdaFunction(): LambdaFunction;
220
+ }