low-cost-ecs 0.0.6
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/.gitattributes +23 -0
- package/.jsii +3394 -0
- package/.projenrc.ts +49 -0
- package/API.md +1184 -0
- package/LICENSE +19 -0
- package/README.md +117 -0
- package/bin/low-cost-ecs.ts +15 -0
- package/cdk.json +3 -0
- package/containers/nginx-proxy/Dockerfile +3 -0
- package/containers/nginx-proxy/templates/default.conf.template +15 -0
- package/containers/nginx-proxy/templates/http_to_https_redirect.conf.template +6 -0
- package/containers/nginx-proxy/templates/https.conf.template +33 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +14 -0
- package/lib/low-cost-ecs.d.ts +102 -0
- package/lib/low-cost-ecs.js +273 -0
- package/package.json +139 -0
- package/todo.md +4 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.LowCostECS = void 0;
|
|
5
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const lib = require("aws-cdk-lib");
|
|
8
|
+
const ec2 = require("aws-cdk-lib/aws-ec2");
|
|
9
|
+
const ecs = require("aws-cdk-lib/aws-ecs");
|
|
10
|
+
const aws_efs_1 = require("aws-cdk-lib/aws-efs");
|
|
11
|
+
const aws_events_1 = require("aws-cdk-lib/aws-events");
|
|
12
|
+
const aws_events_targets_1 = require("aws-cdk-lib/aws-events-targets");
|
|
13
|
+
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
|
|
14
|
+
const aws_logs_1 = require("aws-cdk-lib/aws-logs");
|
|
15
|
+
const route53 = require("aws-cdk-lib/aws-route53");
|
|
16
|
+
const aws_sns_1 = require("aws-cdk-lib/aws-sns");
|
|
17
|
+
const sfn = require("aws-cdk-lib/aws-stepfunctions");
|
|
18
|
+
const sfn_tasks = require("aws-cdk-lib/aws-stepfunctions-tasks");
|
|
19
|
+
;
|
|
20
|
+
class LowCostECS extends lib.Stack {
|
|
21
|
+
constructor(scope, id, props) {
|
|
22
|
+
super(scope, id, props);
|
|
23
|
+
const vpc = props.vpc ??
|
|
24
|
+
new ec2.Vpc(this, 'Vpc', {
|
|
25
|
+
natGateways: 0,
|
|
26
|
+
subnetConfiguration: [
|
|
27
|
+
{
|
|
28
|
+
name: 'PublicSubnet',
|
|
29
|
+
subnetType: ec2.SubnetType.PUBLIC,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
});
|
|
33
|
+
const cluster = new ecs.Cluster(this, 'Cluster', {
|
|
34
|
+
vpc,
|
|
35
|
+
containerInsights: props.containerInsights,
|
|
36
|
+
});
|
|
37
|
+
const hostAutoScalingGroup = cluster.addCapacity('HostInstanceCapacity', {
|
|
38
|
+
machineImage: ecs.EcsOptimizedImage.amazonLinux2(ecs.AmiHardwareType.STANDARD, {
|
|
39
|
+
cachedInContext: true,
|
|
40
|
+
}),
|
|
41
|
+
instanceType: new ec2.InstanceType(props.hostInstanceType ?? 't2.micro'),
|
|
42
|
+
spotPrice: props.hostInstanceSpotPrice,
|
|
43
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
|
|
44
|
+
associatePublicIpAddress: true,
|
|
45
|
+
minCapacity: 1,
|
|
46
|
+
maxCapacity: 1,
|
|
47
|
+
});
|
|
48
|
+
if (props.securityGroup) {
|
|
49
|
+
hostAutoScalingGroup.addSecurityGroup(props.securityGroup);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
hostAutoScalingGroup.connections.allowFromAnyIpv4(ec2.Port.tcp(80));
|
|
53
|
+
hostAutoScalingGroup.connections.allowFromAnyIpv4(ec2.Port.tcp(443));
|
|
54
|
+
hostAutoScalingGroup.connections.allowFrom(ec2.Peer.anyIpv6(), ec2.Port.tcp(80));
|
|
55
|
+
hostAutoScalingGroup.connections.allowFrom(ec2.Peer.anyIpv6(), ec2.Port.tcp(443));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Add managed policy to allow ssh through ssm manager
|
|
59
|
+
*/
|
|
60
|
+
hostAutoScalingGroup.role.addManagedPolicy(aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'));
|
|
61
|
+
/**
|
|
62
|
+
* Add policy to associate elastic ip on startup
|
|
63
|
+
*/
|
|
64
|
+
hostAutoScalingGroup.role.addToPrincipalPolicy(new aws_iam_1.PolicyStatement({
|
|
65
|
+
effect: aws_iam_1.Effect.ALLOW,
|
|
66
|
+
actions: ['ec2:DescribeAddresses', 'ec2:AssociateAddress'],
|
|
67
|
+
resources: ['*'],
|
|
68
|
+
}));
|
|
69
|
+
const hostInstanceIp = new ec2.CfnEIP(this, 'HostInstanceIp');
|
|
70
|
+
const tagUniqueId = lib.Names.uniqueId(hostInstanceIp);
|
|
71
|
+
hostInstanceIp.tags.setTag('Name', tagUniqueId);
|
|
72
|
+
const awsCliTag = props.awsCliDockerTag ?? 'latest';
|
|
73
|
+
hostAutoScalingGroup.addUserData('INSTANCE_ID=$(curl --silent http://169.254.169.254/latest/meta-data/instance-id)', `ALLOCATION_ID=$(docker run --net=host amazon/aws-cli:${awsCliTag} ec2 describe-addresses --region ${hostAutoScalingGroup.env.region} --filter Name=tag:Name,Values=${tagUniqueId} --query 'Addresses[].AllocationId' --output text | head)`, `docker run --net=host amazon/aws-cli:${awsCliTag} ec2 associate-address --region ${hostAutoScalingGroup.env.region} --instance-id "$INSTANCE_ID" --allocation-id "$ALLOCATION_ID" --allow-reassociation`);
|
|
74
|
+
const certFileSystem = new aws_efs_1.FileSystem(this, 'FileSystem', {
|
|
75
|
+
vpc,
|
|
76
|
+
encrypted: true,
|
|
77
|
+
securityGroup: new ec2.SecurityGroup(this, 'FileSystemSecurityGroup', {
|
|
78
|
+
vpc,
|
|
79
|
+
allowAllOutbound: false,
|
|
80
|
+
}),
|
|
81
|
+
removalPolicy: props.removalPolicy ?? lib.RemovalPolicy.DESTROY,
|
|
82
|
+
});
|
|
83
|
+
certFileSystem.connections.allowDefaultPortTo(hostAutoScalingGroup);
|
|
84
|
+
certFileSystem.connections.allowDefaultPortFrom(hostAutoScalingGroup);
|
|
85
|
+
/**
|
|
86
|
+
* ARecord to Elastic ip
|
|
87
|
+
*/
|
|
88
|
+
const hostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {
|
|
89
|
+
domainName: props.hostedZoneDomain,
|
|
90
|
+
});
|
|
91
|
+
const records = props.recordDomainNames ?? [hostedZone.zoneName];
|
|
92
|
+
records.forEach((record) => new route53.ARecord(this, `ARecord${record}`, {
|
|
93
|
+
zone: hostedZone,
|
|
94
|
+
recordName: record,
|
|
95
|
+
target: route53.RecordTarget.fromIpAddresses(hostInstanceIp.ref),
|
|
96
|
+
}));
|
|
97
|
+
/**
|
|
98
|
+
* Certbot Task Definition
|
|
99
|
+
* Mounts generated certificate to EFS
|
|
100
|
+
*/
|
|
101
|
+
const logGroup = props.logGroup ??
|
|
102
|
+
new aws_logs_1.LogGroup(this, 'LogGroup', {
|
|
103
|
+
retention: aws_logs_1.RetentionDays.TWO_YEARS,
|
|
104
|
+
removalPolicy: props.removalPolicy ?? lib.RemovalPolicy.DESTROY,
|
|
105
|
+
});
|
|
106
|
+
const certbotTaskDefinition = new ecs.Ec2TaskDefinition(this, 'CertbotTaskDefinition');
|
|
107
|
+
certbotTaskDefinition.addToTaskRolePolicy(new aws_iam_1.PolicyStatement({
|
|
108
|
+
effect: aws_iam_1.Effect.ALLOW,
|
|
109
|
+
actions: ['route53:ListHostedZones', 'route53:GetChange'],
|
|
110
|
+
resources: ['*'],
|
|
111
|
+
}));
|
|
112
|
+
certbotTaskDefinition.addToTaskRolePolicy(new aws_iam_1.PolicyStatement({
|
|
113
|
+
effect: aws_iam_1.Effect.ALLOW,
|
|
114
|
+
actions: ['route53:ChangeResourceRecordSets'],
|
|
115
|
+
resources: [hostedZone.hostedZoneArn],
|
|
116
|
+
}));
|
|
117
|
+
const certbotTag = props.certbotDockerTag ?? 'v1.29.0';
|
|
118
|
+
const certbotContainer = certbotTaskDefinition.addContainer('CertbotContainer', {
|
|
119
|
+
image: ecs.ContainerImage.fromRegistry(`certbot/dns-route53:${certbotTag}`),
|
|
120
|
+
containerName: 'certbot',
|
|
121
|
+
memoryReservationMiB: 64,
|
|
122
|
+
command: [
|
|
123
|
+
'certonly',
|
|
124
|
+
'--verbose',
|
|
125
|
+
'--preferred-challenges=dns-01',
|
|
126
|
+
'--dns-route53',
|
|
127
|
+
'--dns-route53-propagation-seconds=300',
|
|
128
|
+
'--non-interactive',
|
|
129
|
+
'--agree-tos',
|
|
130
|
+
'--expand',
|
|
131
|
+
'-m',
|
|
132
|
+
props.email,
|
|
133
|
+
'--cert-name',
|
|
134
|
+
records[0],
|
|
135
|
+
...records.flatMap((domain) => ['-d', domain]),
|
|
136
|
+
],
|
|
137
|
+
logging: ecs.LogDriver.awsLogs({
|
|
138
|
+
logGroup,
|
|
139
|
+
streamPrefix: certbotTag,
|
|
140
|
+
}),
|
|
141
|
+
});
|
|
142
|
+
certFileSystem.grant(certbotTaskDefinition.taskRole, 'elasticfilesystem:ClientWrite');
|
|
143
|
+
certbotTaskDefinition.addVolume({
|
|
144
|
+
name: 'certVolume',
|
|
145
|
+
efsVolumeConfiguration: {
|
|
146
|
+
fileSystemId: certFileSystem.fileSystemId,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
certbotContainer.addMountPoints({
|
|
150
|
+
sourceVolume: 'certVolume',
|
|
151
|
+
containerPath: '/etc/letsencrypt',
|
|
152
|
+
readOnly: false,
|
|
153
|
+
});
|
|
154
|
+
/**
|
|
155
|
+
* Schedule Certbot certificate create/renew on Step Functions
|
|
156
|
+
* Sends email notification on certbot failure
|
|
157
|
+
*/
|
|
158
|
+
const topic = new aws_sns_1.Topic(this, 'Topic');
|
|
159
|
+
new aws_sns_1.Subscription(this, 'EmailSubscription', {
|
|
160
|
+
topic: topic,
|
|
161
|
+
protocol: aws_sns_1.SubscriptionProtocol.EMAIL,
|
|
162
|
+
endpoint: props.email,
|
|
163
|
+
});
|
|
164
|
+
const certbotRunTask = new sfn_tasks.EcsRunTask(this, 'CreateCertificate', {
|
|
165
|
+
cluster: cluster,
|
|
166
|
+
taskDefinition: certbotTaskDefinition,
|
|
167
|
+
launchTarget: new sfn_tasks.EcsEc2LaunchTarget(),
|
|
168
|
+
integrationPattern: sfn.IntegrationPattern.RUN_JOB,
|
|
169
|
+
});
|
|
170
|
+
certbotRunTask.addCatch(new sfn_tasks.SnsPublish(this, 'SendEmailOnFailure', {
|
|
171
|
+
topic: topic,
|
|
172
|
+
message: sfn.TaskInput.fromJsonPathAt('$'),
|
|
173
|
+
}).next(new sfn.Fail(this, 'Fail')));
|
|
174
|
+
certbotRunTask.addRetry({
|
|
175
|
+
interval: lib.Duration.seconds(20),
|
|
176
|
+
});
|
|
177
|
+
const certbotStateMachine = new sfn.StateMachine(this, 'StateMachine', {
|
|
178
|
+
definition: certbotRunTask,
|
|
179
|
+
});
|
|
180
|
+
new aws_events_1.Rule(this, 'CertbotScheduleRule', {
|
|
181
|
+
schedule: aws_events_1.Schedule.rate(lib.Duration.days(props.certbotScheduleInterval ?? 60)),
|
|
182
|
+
targets: [new aws_events_targets_1.SfnStateMachine(certbotStateMachine)],
|
|
183
|
+
});
|
|
184
|
+
/**
|
|
185
|
+
* Server ECS task
|
|
186
|
+
*/
|
|
187
|
+
const serverTaskDefinition = props.serverTaskDefinition ?? this.sampleSeverTask(records, logGroup);
|
|
188
|
+
certFileSystem.grant(serverTaskDefinition.taskRole, 'elasticfilesystem:ClientMount');
|
|
189
|
+
serverTaskDefinition.addVolume({
|
|
190
|
+
name: 'certVolume',
|
|
191
|
+
efsVolumeConfiguration: {
|
|
192
|
+
fileSystemId: certFileSystem.fileSystemId,
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
serverTaskDefinition.defaultContainer?.addMountPoints({
|
|
196
|
+
sourceVolume: 'certVolume',
|
|
197
|
+
containerPath: '/etc/letsencrypt',
|
|
198
|
+
readOnly: true,
|
|
199
|
+
});
|
|
200
|
+
/**
|
|
201
|
+
* AWS cli container to execute certbot sfn before the default container startup.
|
|
202
|
+
*/
|
|
203
|
+
serverTaskDefinition.defaultContainer?.addContainerDependencies({
|
|
204
|
+
container: serverTaskDefinition.addContainer('AWSCliContainer', {
|
|
205
|
+
image: ecs.ContainerImage.fromRegistry(`amazon/aws-cli:${awsCliTag}`),
|
|
206
|
+
containerName: 'aws-cli',
|
|
207
|
+
memoryReservationMiB: 64,
|
|
208
|
+
entryPoint: ['/bin/bash', '-c'],
|
|
209
|
+
command: [
|
|
210
|
+
`set -eux
|
|
211
|
+
aws configure set region ${certbotStateMachine.env.region} && \\
|
|
212
|
+
aws configure set output text && \\
|
|
213
|
+
EXECUTION_ARN=$(aws stepfunctions start-execution --state-machine-arn ${certbotStateMachine.stateMachineArn} --query executionArn) && \\
|
|
214
|
+
until [ $(aws stepfunctions describe-execution --execution-arn "$EXECUTION_ARN" --query status) != RUNNING ];
|
|
215
|
+
do
|
|
216
|
+
echo "Waiting for $EXECUTION_ARN"
|
|
217
|
+
sleep 10
|
|
218
|
+
done`,
|
|
219
|
+
],
|
|
220
|
+
essential: false,
|
|
221
|
+
logging: ecs.LogDriver.awsLogs({
|
|
222
|
+
logGroup: logGroup,
|
|
223
|
+
streamPrefix: awsCliTag,
|
|
224
|
+
}),
|
|
225
|
+
}),
|
|
226
|
+
condition: ecs.ContainerDependencyCondition.COMPLETE,
|
|
227
|
+
});
|
|
228
|
+
certbotStateMachine.grantExecution(serverTaskDefinition.taskRole, 'states:DescribeExecution');
|
|
229
|
+
certbotStateMachine.grantStartExecution(serverTaskDefinition.taskRole);
|
|
230
|
+
new ecs.Ec2Service(this, 'Service', {
|
|
231
|
+
cluster: cluster,
|
|
232
|
+
taskDefinition: serverTaskDefinition,
|
|
233
|
+
desiredCount: 1,
|
|
234
|
+
minHealthyPercent: 0,
|
|
235
|
+
maxHealthyPercent: 100,
|
|
236
|
+
circuitBreaker: {
|
|
237
|
+
rollback: true,
|
|
238
|
+
},
|
|
239
|
+
enableExecuteCommand: true,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
sampleSeverTask(records, logGroup) {
|
|
243
|
+
const nginxTaskDefinition = new ecs.Ec2TaskDefinition(this, 'NginxTaskDefinition');
|
|
244
|
+
const nginxContainer = nginxTaskDefinition.addContainer('NginxContainer', {
|
|
245
|
+
image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../containers/nginx-proxy')),
|
|
246
|
+
containerName: 'nginx',
|
|
247
|
+
memoryReservationMiB: 64,
|
|
248
|
+
essential: true,
|
|
249
|
+
environment: {
|
|
250
|
+
SERVER_NAME: records.join(' '),
|
|
251
|
+
CERT_NAME: records[0],
|
|
252
|
+
},
|
|
253
|
+
logging: ecs.LogDrivers.awsLogs({
|
|
254
|
+
logGroup: logGroup,
|
|
255
|
+
streamPrefix: 'nginx-proxy',
|
|
256
|
+
}),
|
|
257
|
+
});
|
|
258
|
+
nginxContainer.addPortMappings({
|
|
259
|
+
hostPort: 80,
|
|
260
|
+
containerPort: 80,
|
|
261
|
+
protocol: ecs.Protocol.TCP,
|
|
262
|
+
}, {
|
|
263
|
+
hostPort: 443,
|
|
264
|
+
containerPort: 443,
|
|
265
|
+
protocol: ecs.Protocol.TCP,
|
|
266
|
+
});
|
|
267
|
+
return nginxTaskDefinition;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
exports.LowCostECS = LowCostECS;
|
|
271
|
+
_a = JSII_RTTI_SYMBOL_1;
|
|
272
|
+
LowCostECS[_a] = { fqn: "low-cost-ecs.LowCostECS", version: "0.0.6" };
|
|
273
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG93LWNvc3QtZWNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2xvdy1jb3N0LWVjcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZCQUE2QjtBQUM3QixtQ0FBbUM7QUFDbkMsMkNBQTJDO0FBQzNDLDJDQUEyQztBQUMzQyxpREFBaUQ7QUFDakQsdURBQXdEO0FBQ3hELHVFQUFpRTtBQUNqRSxpREFBNkU7QUFDN0UsbURBQTBFO0FBQzFFLG1EQUFtRDtBQUNuRCxpREFBZ0Y7QUFDaEYscURBQXFEO0FBQ3JELGlFQUFpRTtBQTRHaEUsQ0FBQztBQUVGLE1BQWEsVUFBVyxTQUFRLEdBQUcsQ0FBQyxLQUFLO0lBQ3ZDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBc0I7UUFDOUQsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFeEIsTUFBTSxHQUFHLEdBQ1AsS0FBSyxDQUFDLEdBQUc7WUFDVCxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRTtnQkFDdkIsV0FBVyxFQUFFLENBQUM7Z0JBQ2QsbUJBQW1CLEVBQUU7b0JBQ25CO3dCQUNFLElBQUksRUFBRSxjQUFjO3dCQUNwQixVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxNQUFNO3FCQUNsQztpQkFDRjthQUNGLENBQUMsQ0FBQztRQUVMLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFO1lBQy9DLEdBQUc7WUFDSCxpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO1NBQzNDLENBQUMsQ0FBQztRQUVILE1BQU0sb0JBQW9CLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxzQkFBc0IsRUFBRTtZQUN2RSxZQUFZLEVBQUUsR0FBRyxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FDOUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxRQUFR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Q0FDckIsT0FBaUIsRUFDakIsUUFBbUI7UUFFbkIsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxpQkFBaUIsQ0FDbkQsSUFBSSxFQUNKLHFCQUFxQixDQUN0QixDQUFDO1FBQ0YsTUFBTSxjQUFjLEdBQUcsbUJBQW1CLENBQUMsWUFBWSxDQUFDLGdCQUFnQixFQUFFO1lBQ3hFLEtBQUssRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FDakMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsMkJBQTJCLENBQUMsQ0FDbEQ7WUFDRCxhQUFhLEVBQUUsT0FBTztZQUN0QixvQkFBb0IsRUFBRSxFQUFFO1lBQ3hCLFNBQVMsRUFBRSxJQUFJO1lBQ2YsV0FBVyxFQUFFO2dCQUNYLFdBQVcsRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztnQkFDOUIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7YUFDdEI7WUFDRCxPQUFPLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUM7Z0JBQzlCLFFBQVEsRUFBRSxRQUFRO2dCQUNsQixZQUFZLEVBQUUsYUFBYTthQUM1QixDQUFDO1NBQ0gsQ0FBQyxDQUFDO1FBRUgsY0FBYyxDQUFDLGVBQWUsQ0FDNUI7WUFDRSxRQUFRLEVBQUUsRUFBRTtZQUNaLGFBQWEsRUFBRSxFQUFFO1lBQ2pCLFFBQVEsRUFBRSxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUc7U0FDM0IsRUFDRDtZQUNFLFFBQVEsRUFBRSxHQUFHO1lBQ2IsYUFBYSxFQUFFLEdBQUc7WUFDbEIsUUFBUSxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRztTQUMzQixDQUNGLENBQUM7UUFFRixPQUFPLG1CQUFtQixDQUFDO0lBQzdCLENBQUM7O0FBeFVILGdDQXlVQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBsaWIgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgZWNzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lY3MnO1xuaW1wb3J0IHsgRmlsZVN5c3RlbSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lZnMnO1xuaW1wb3J0IHsgUnVsZSwgU2NoZWR1bGUgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZXZlbnRzJztcbmltcG9ydCB7IFNmblN0YXRlTWFjaGluZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1ldmVudHMtdGFyZ2V0cyc7XG5pbXBvcnQgeyBFZmZlY3QsIE1hbmFnZWRQb2xpY3ksIFBvbGljeVN0YXRlbWVudCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgSUxvZ0dyb3VwLCBMb2dHcm91cCwgUmV0ZW50aW9uRGF5cyB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sb2dzJztcbmltcG9ydCAqIGFzIHJvdXRlNTMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXJvdXRlNTMnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uLCBTdWJzY3JpcHRpb25Qcm90b2NvbCwgVG9waWMgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc25zJztcbmltcG9ydCAqIGFzIHNmbiBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3RlcGZ1bmN0aW9ucyc7XG5pbXBvcnQgKiBhcyBzZm5fdGFza3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMtdGFza3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG93Q29zdEVDU1Byb3BzIGV4dGVuZHMgbGliLlN0YWNrUHJvcHMge1xuICAvKipcbiAgICogRG9tYWluIG5hbWUgb2YgdGhlIGhvc3RlZCB6b25lLlxuICAgKi9cbiAgcmVhZG9ubHkgaG9zdGVkWm9uZURvbWFpbjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBFbWFpbCBmb3IgZXhwaXJhdGlvbiBlbWFpbHMgdG8gcmVnaXN0ZXIgdG8geW91ciBsZXQncyBlbmNyeXB0IGFjY291bnQuXG4gICAqXG4gICAqIEBsaW5rIGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL2RvY3MvZXhwaXJhdGlvbi1lbWFpbHMvXG4gICAqXG4gICAqIEFsc28gcmVnaXN0ZXJlZCBhcyBhIHN1YnNjcmliZXIgb2YgdGhlIHNucyB0b3BpYywgbm90aWZpZWQgb24gY2VydGJvdCB0YXNrIGZhaWx1cmUuXG4gICAqIFN1YnNjcmlwdGlvbiBjb25maXJtYXRpb24gZW1haWwgd291bGQgYmUgc2VudCBvbiBzdGFjayBjcmVhdGlvbi5cbiAgICpcbiAgICogQGxpbmsgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3Nucy9sYXRlc3QvZGcvc25zLWVtYWlsLW5vdGlmaWNhdGlvbnMuaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgZW1haWw6IHN0cmluZztcblxuICAvKipcbiAgICogRG9tYWluIG5hbWVzIGZvciBBIHJlY29yZHMgdG8gZWxhc3RpYyBpcCBvZiBFQ1MgaG9zdCBpbnN0YW5jZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBbIHByb3BzLmhvc3RlZFpvbmUuem9uZU5hbWUgXVxuICAgKi9cbiAgcmVhZG9ubHkgcmVjb3JkRG9tYWluTmFtZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVnBjIG9mIHRoZSBFQ1MgaG9zdCBpbnN0YW5jZSBhbmQgY2x1c3Rlci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBDcmVhdGVzIHZwYyB3aXRoIG9ubHkgcHVibGljIHN1Ym5ldHMgYW5kIG5vIE5BVCBnYXRld2F5cy5cbiAgICovXG4gIHJlYWRvbmx5IHZwYz86IGVjMi5JVnBjO1xuXG4gIC8qKlxuICAgKiBTZWN1cml0eSBncm91cCBvZiB0aGUgRUNTIGhvc3QgaW5zdGFuY2VcbiAgICpcbiAgICogQGRlZmF1bHQgLSBDcmVhdGVzIHNlY3VyaXR5IGdyb3VwIHdpdGggYWxsb3dBbGxPdXRib3VuZCBhbmQgaW5ncmVzcyBydWxlIChpcHY0LCBpcHY2KSA9PiAodGNwIDgwLCA0NDMpLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cD86IGVjMi5TZWN1cml0eUdyb3VwO1xuXG4gIC8qKlxuICAgKiBJbnN0YW5jZSB0eXBlIG9mIHRoZSBFQ1MgaG9zdCBpbnN0YW5jZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0Mi5taWNyb1xuICAgKi9cbiAgcmVhZG9ubHkgaG9zdEluc3RhbmNlVHlwZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG1heGltdW0gaG91cmx5IHByaWNlIChpbiBVU0QpIHRvIGJlIHBhaWQgZm9yIGFueSBTcG90IEluc3RhbmNlIGxhdW5jaGVkIHRvIGZ1bGZpbGwgdGhlIHJlcXVlc3QuXG4gICAqIEhvc3QgaW5zdGFuY2UgYXNnIHdvdWxkIHVzZSBzcG90IGluc3RhbmNlcyBpZiBob3N0SW5zdGFuY2VTcG90UHJpY2UgaXMgc2V0LlxuICAgKlxuICAgKiBAbGluayBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2RrL2FwaS92Mi9kb2NzL2F3cy1jZGstbGliLmF3c19lY3MuQWRkQ2FwYWNpdHlPcHRpb25zLmh0bWwjc3BvdHByaWNlXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBob3N0SW5zdGFuY2VTcG90UHJpY2U/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIExvZyBncm91cCBvZiB0aGUgY2VydGJvdCB0YXNrIGFuZCB0aGUgYXdzLWNsaSB0YXNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIENyZWF0ZXMgZGVmYXVsdCBjZGsgbG9nIGdyb3VwXG4gICAqL1xuICByZWFkb25seSBsb2dHcm91cD86IElMb2dHcm91cDtcblxuICAvKipcbiAgICogRG9ja2VyIGltYWdlIHRhZyBvZiBjZXJ0Ym90L2Rucy1yb3V0ZTUzIHRvIGNyZWF0ZSBjZXJ0aWZpY2F0ZXMuXG4gICAqXG4gICAqIEBsaW5rIGh0dHBzOi8vaHViLmRvY2tlci5jb20vci9jZXJ0Ym90L2Rucy1yb3V0ZTUzL3RhZ3NcbiAgICogQGRlZmF1bHQgLSB2MS4yOS4wXG4gICAqL1xuICByZWFkb25seSBjZXJ0Ym90RG9ja2VyVGFnPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDZXJ0Ym90IHRhc2sgc2NoZWR1bGUgaW50ZXJ2YWwgaW4gZGF5cyB0byByZW5ldyB0aGUgY2VydGlmaWNhdGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gNjBcbiAgICovXG4gIHJlYWRvbmx5IGNlcnRib3RTY2hlZHVsZUludGVydmFsPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBEb2NrZXIgaW1hZ2UgdGFnIG9mIGFtYXpvbi9hd3MtY2xpLlxuICAgKiBUaGlzIGltYWdlIGlzIHVzZWQgdG8gYXNzb2NpYXRlIGVsYXN0aWMgaXAgb24gaG9zdCBpbnN0YW5jZSBzdGFydHVwLCBhbmQgcnVuIGNlcnRib3QgY2ZuIG9uIGVjcyBjb250YWluZXIgc3RhcnR1cC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBsYXRlc3RcbiAgICovXG4gIHJlYWRvbmx5IGF3c0NsaURvY2tlclRhZz86IHN0cmluZztcblxuICAvKipcbiAgICogRW5hYmxlIGNvbnRhaW5lciBpbnNpZ2h0cyBvciBub3RcbiAgICpcbiAgICogQGRlZmF1bHQgLSB1bmRlZmluZWQgKGNvbnRhaW5lciBpbnNpZ2h0cyBkaXNhYmxlZClcbiAgICovXG4gIHJlYWRvbmx5IGNvbnRhaW5lckluc2lnaHRzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogUmVtb3ZhbCBwb2xpY3kgZm9yIHRoZSBmaWxlIHN5c3RlbSBhbmQgbG9nIGdyb3VwIChpZiB1c2luZyBkZWZhdWx0KS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBSZW1vdmFsUG9saWN5LkRFU1RST1lcbiAgICovXG4gIHJlYWRvbmx5IHJlbW92YWxQb2xpY3k/OiBsaWIuUmVtb3ZhbFBvbGljeTtcblxuICAvKipcbiAgICogVGFzayBkZWZpbml0aW9uIGZvciB0aGUgc2VydmVyIGVjcyB0YXNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5naW54IHNlcnZlciB0YXNrIGRlZmluaXRpb24gZGVmaW5lZCBpbiBzYW1wbGVTZXJ2ZXJUYXNrKClcbiAgICovXG4gIHJlYWRvbmx5IHNlcnZlclRhc2tEZWZpbml0aW9uPzogZWNzLkVjMlRhc2tEZWZpbml0aW9uO1xufTtcblxuZXhwb3J0IGNsYXNzIExvd0Nvc3RFQ1MgZXh0ZW5kcyBsaWIuU3RhY2sge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogTG93Q29zdEVDU1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICBjb25zdCB2cGMgPVxuICAgICAgcHJvcHMudnBjID8/XG4gICAgICBuZXcgZWMyLlZwYyh0aGlzLCAnVnBjJywge1xuICAgICAgICBuYXRHYXRld2F5czogMCxcbiAgICAgICAgc3VibmV0Q29uZmlndXJhdGlvbjogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdQdWJsaWNTdWJuZXQnLFxuICAgICAgICAgICAgc3VibmV0VHlwZTogZWMyLlN1Ym5ldFR5cGUuUFVCTElDLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgIGNvbnN0IGNsdXN0ZXIgPSBuZXcgZWNzLkNsdXN0ZXIodGhpcywgJ0NsdXN0ZXInLCB7XG4gICAgICB2cGMsXG4gICAgICBjb250YWluZXJJbnNpZ2h0czogcHJvcHMuY29udGFpbmVySW5zaWdodHMsXG4gICAgfSk7XG5cbiAgICBjb25zdCBob3N0QXV0b1NjYWxpbmdHcm91cCA9IGNsdXN0ZXIuYWRkQ2FwYWNpdHkoJ0hvc3RJbnN0YW5jZUNhcGFjaXR5Jywge1xuICAgICAgbWFjaGluZUltYWdlOiBlY3MuRWNzT3B0aW1pemVkSW1hZ2UuYW1hem9uTGludXgyKFxuICAgICAgICBlY3MuQW1pSGFyZHdhcmVUeXBlLlNUQU5EQVJELFxuICAgICAgICB7XG4gICAgICAgICAgY2FjaGVkSW5Db250ZXh0OiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgKSxcbiAgICAgIGluc3RhbmNlVHlwZTogbmV3IGVjMi5JbnN0YW5jZVR5cGUocHJvcHMuaG9zdEluc3RhbmNlVHlwZSA/PyAndDIubWljcm8nKSxcbiAgICAgIHNwb3RQcmljZTogcHJvcHMuaG9zdEluc3RhbmNlU3BvdFByaWNlLFxuICAgICAgdnBjU3VibmV0czogeyBzdWJuZXRUeXBlOiBlYzIuU3VibmV0VHlwZS5QVUJMSUMgfSxcbiAgICAgIGFzc29jaWF0ZVB1YmxpY0lwQWRkcmVzczogdHJ1ZSxcbiAgICAgIG1pbkNhcGFjaXR5OiAxLFxuICAgICAgbWF4Q2FwYWNpdHk6IDEsXG4gICAgfSk7XG5cbiAgICBpZiAocHJvcHMuc2VjdXJpdHlHcm91cCkge1xuICAgICAgaG9zdEF1dG9TY2FsaW5nR3JvdXAuYWRkU2VjdXJpdHlHcm91cChwcm9wcy5zZWN1cml0eUdyb3VwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaG9zdEF1dG9TY2FsaW5nR3JvdXAuY29ubmVjdGlvbnMuYWxsb3dGcm9tQW55SXB2NChlYzIuUG9ydC50Y3AoODApKTtcbiAgICAgIGhvc3RBdXRvU2NhbGluZ0dyb3VwLmNvbm5lY3Rpb25zLmFsbG93RnJvbUFueUlwdjQoZWMyLlBvcnQudGNwKDQ0MykpO1xuICAgICAgaG9zdEF1dG9TY2FsaW5nR3JvdXAuY29ubmVjdGlvbnMuYWxsb3dGcm9tKFxuICAgICAgICBlYzIuUGVlci5hbnlJcHY2KCksXG4gICAgICAgIGVjMi5Qb3J0LnRjcCg4MCksXG4gICAgICApO1xuICAgICAgaG9zdEF1dG9TY2FsaW5nR3JvdXAuY29ubmVjdGlvbnMuYWxsb3dGcm9tKFxuICAgICAgICBlYzIuUGVlci5hbnlJcHY2KCksXG4gICAgICAgIGVjMi5Qb3J0LnRjcCg0NDMpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgbWFuYWdlZCBwb2xpY3kgdG8gYWxsb3cgc3NoIHRocm91Z2ggc3NtIG1hbmFnZXJcbiAgICAgKi9cbiAgICBob3N0QXV0b1NjYWxpbmdHcm91cC5yb2xlLmFkZE1hbmFnZWRQb2xpY3koXG4gICAgICBNYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZSgnQW1hem9uU1NNTWFuYWdlZEluc3RhbmNlQ29yZScpLFxuICAgICk7XG4gICAgLyoqXG4gICAgICogQWRkIHBvbGljeSB0byBhc3NvY2lhdGUgZWxhc3RpYyBpcCBvbiBzdGFydHVwXG4gICAgICovXG4gICAgaG9zdEF1dG9TY2FsaW5nR3JvdXAucm9sZS5hZGRUb1ByaW5jaXBhbFBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogWydlYzI6RGVzY3JpYmVBZGRyZXNzZXMnLCAnZWMyOkFzc29jaWF0ZUFkZHJlc3MnXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBjb25zdCBob3N0SW5zdGFuY2VJcCA9IG5ldyBlYzIuQ2ZuRUlQKHRoaXMsICdIb3N0SW5zdGFuY2VJcCcpO1xuICAgIGNvbnN0IHRhZ1VuaXF1ZUlkID0gbGliLk5hbWVzLnVuaXF1ZUlkKGhvc3RJbnN0YW5jZUlwKTtcbiAgICBob3N0SW5zdGFuY2VJcC50YWdzLnNldFRhZygnTmFtZScsIHRhZ1VuaXF1ZUlkKTtcblxuICAgIGNvbnN0IGF3c0NsaVRhZyA9IHByb3BzLmF3c0NsaURvY2tlclRhZyA/PyAnbGF0ZXN0JztcbiAgICBob3N0QXV0b1NjYWxpbmdHcm91cC5hZGRVc2VyRGF0YShcbiAgICAgICdJTlNUQU5DRV9JRD0kKGN1cmwgLS1zaWxlbnQgaHR0cDovLzE2OS4yNTQuMTY5LjI1NC9sYXRlc3QvbWV0YS1kYXRhL2luc3RhbmNlLWlkKScsXG4gICAgICBgQUxMT0NBVElPTl9JRD0kKGRvY2tlciBydW4gLS1uZXQ9aG9zdCBhbWF6b24vYXdzLWNsaToke2F3c0NsaVRhZ30gZWMyIGRlc2NyaWJlLWFkZHJlc3NlcyAtLXJlZ2lvbiAke2hvc3RBdXRvU2NhbGluZ0dyb3VwLmVudi5yZWdpb259IC0tZmlsdGVyIE5hbWU9dGFnOk5hbWUsVmFsdWVzPSR7dGFnVW5pcXVlSWR9IC0tcXVlcnkgJ0FkZHJlc3Nlc1tdLkFsbG9jYXRpb25JZCcgLS1vdXRwdXQgdGV4dCB8IGhlYWQpYCxcbiAgICAgIGBkb2NrZXIgcnVuIC0tbmV0PWhvc3QgYW1hem9uL2F3cy1jbGk6JHthd3NDbGlUYWd9IGVjMiBhc3NvY2lhdGUtYWRkcmVzcyAtLXJlZ2lvbiAke2hvc3RBdXRvU2NhbGluZ0dyb3VwLmVudi5yZWdpb259IC0taW5zdGFuY2UtaWQgXCIkSU5TVEFOQ0VfSURcIiAtLWFsbG9jYXRpb24taWQgXCIkQUxMT0NBVElPTl9JRFwiIC0tYWxsb3ctcmVhc3NvY2lhdGlvbmAsXG4gICAgKTtcblxuICAgIGNvbnN0IGNlcnRGaWxlU3lzdGVtID0gbmV3IEZpbGVTeXN0ZW0odGhpcywgJ0ZpbGVTeXN0ZW0nLCB7XG4gICAgICB2cGMsXG4gICAgICBlbmNyeXB0ZWQ6IHRydWUsXG4gICAgICBzZWN1cml0eUdyb3VwOiBuZXcgZWMyLlNlY3VyaXR5R3JvdXAodGhpcywgJ0ZpbGVTeXN0ZW1TZWN1cml0eUdyb3VwJywge1xuICAgICAgICB2cGMsXG4gICAgICAgIGFsbG93QWxsT3V0Ym91bmQ6IGZhbHNlLFxuICAgICAgfSksXG4gICAgICByZW1vdmFsUG9saWN5OiBwcm9wcy5yZW1vdmFsUG9saWN5ID8/IGxpYi5SZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgfSk7XG4gICAgY2VydEZpbGVTeXN0ZW0uY29ubmVjdGlvbnMuYWxsb3dEZWZhdWx0UG9ydFRvKGhvc3RBdXRvU2NhbGluZ0dyb3VwKTtcbiAgICBjZXJ0RmlsZVN5c3RlbS5jb25uZWN0aW9ucy5hbGxvd0RlZmF1bHRQb3J0RnJvbShob3N0QXV0b1NjYWxpbmdHcm91cCk7XG5cbiAgICAvKipcbiAgICAgKiBBUmVjb3JkIHRvIEVsYXN0aWMgaXBcbiAgICAgKi9cbiAgICBjb25zdCBob3N0ZWRab25lID0gcm91dGU1My5Ib3N0ZWRab25lLmZyb21Mb29rdXAodGhpcywgJ0hvc3RlZFpvbmUnLCB7XG4gICAgICBkb21haW5OYW1lOiBwcm9wcy5ob3N0ZWRab25lRG9tYWluLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlY29yZHMgPSBwcm9wcy5yZWNvcmREb21haW5OYW1lcyA/PyBbaG9zdGVkWm9uZS56b25lTmFtZV07XG4gICAgcmVjb3Jkcy5mb3JFYWNoKFxuICAgICAgKHJlY29yZCkgPT5cbiAgICAgICAgbmV3IHJvdXRlNTMuQVJlY29yZCh0aGlzLCBgQVJlY29yZCR7cmVjb3JkfWAsIHtcbiAgICAgICAgICB6b25lOiBob3N0ZWRab25lLFxuICAgICAgICAgIHJlY29yZE5hbWU6IHJlY29yZCxcbiAgICAgICAgICB0YXJnZXQ6IHJvdXRlNTMuUmVjb3JkVGFyZ2V0LmZyb21JcEFkZHJlc3Nlcyhob3N0SW5zdGFuY2VJcC5yZWYpLFxuICAgICAgICB9KSxcbiAgICApO1xuXG4gICAgLyoqXG4gICAgICogQ2VydGJvdCBUYXNrIERlZmluaXRpb25cbiAgICAgKiBNb3VudHMgZ2VuZXJhdGVkIGNlcnRpZmljYXRlIHRvIEVGU1xuICAgICAqL1xuICAgIGNvbnN0IGxvZ0dyb3VwID1cbiAgICAgIHByb3BzLmxvZ0dyb3VwID8/XG4gICAgICBuZXcgTG9nR3JvdXAodGhpcywgJ0xvZ0dyb3VwJywge1xuICAgICAgICByZXRlbnRpb246IFJldGVudGlvbkRheXMuVFdPX1lFQVJTLFxuICAgICAgICByZW1vdmFsUG9saWN5OiBwcm9wcy5yZW1vdmFsUG9saWN5ID8/IGxpYi5SZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgICB9KTtcblxuICAgIGNvbnN0IGNlcnRib3RUYXNrRGVmaW5pdGlvbiA9IG5ldyBlY3MuRWMyVGFza0RlZmluaXRpb24oXG4gICAgICB0aGlzLFxuICAgICAgJ0NlcnRib3RUYXNrRGVmaW5pdGlvbicsXG4gICAgKTtcbiAgICBjZXJ0Ym90VGFza0RlZmluaXRpb24uYWRkVG9UYXNrUm9sZVBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogWydyb3V0ZTUzOkxpc3RIb3N0ZWRab25lcycsICdyb3V0ZTUzOkdldENoYW5nZSddLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgfSksXG4gICAgKTtcbiAgICBjZXJ0Ym90VGFza0RlZmluaXRpb24uYWRkVG9UYXNrUm9sZVBvbGljeShcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogWydyb3V0ZTUzOkNoYW5nZVJlc291cmNlUmVjb3JkU2V0cyddLFxuICAgICAgICByZXNvdXJjZXM6IFtob3N0ZWRab25lLmhvc3RlZFpvbmVBcm5dLFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IGNlcnRib3RUYWcgPSBwcm9wcy5jZXJ0Ym90RG9ja2VyVGFnID8/ICd2MS4yOS4wJztcbiAgICBjb25zdCBjZXJ0Ym90Q29udGFpbmVyID0gY2VydGJvdFRhc2tEZWZpbml0aW9uLmFkZENvbnRhaW5lcihcbiAgICAgICdDZXJ0Ym90Q29udGFpbmVyJyxcbiAgICAgIHtcbiAgICAgICAgaW1hZ2U6IGVjcy5Db250YWluZXJJbWFnZS5mcm9tUmVnaXN0cnkoXG4gICAgICAgICAgYGNlcnRib3QvZG5zLXJvdXRlNTM6JHtjZXJ0Ym90VGFnfWAsXG4gICAgICAgICksXG4gICAgICAgIGNvbnRhaW5lck5hbWU6ICdjZXJ0Ym90JyxcbiAgICAgICAgbWVtb3J5UmVzZXJ2YXRpb25NaUI6IDY0LFxuICAgICAgICBjb21tYW5kOiBbXG4gICAgICAgICAgJ2NlcnRvbmx5JyxcbiAgICAgICAgICAnLS12ZXJib3NlJyxcbiAgICAgICAgICAnLS1wcmVmZXJyZWQtY2hhbGxlbmdlcz1kbnMtMDEnLFxuICAgICAgICAgICctLWRucy1yb3V0ZTUzJyxcbiAgICAgICAgICAnLS1kbnMtcm91dGU1My1wcm9wYWdhdGlvbi1zZWNvbmRzPTMwMCcsXG4gICAgICAgICAgJy0tbm9uLWludGVyYWN0aXZlJyxcbiAgICAgICAgICAnLS1hZ3JlZS10b3MnLFxuICAgICAgICAgICctLWV4cGFuZCcsXG4gICAgICAgICAgJy1tJyxcbiAgICAgICAgICBwcm9wcy5lbWFpbCxcbiAgICAgICAgICAnLS1jZXJ0LW5hbWUnLFxuICAgICAgICAgIHJlY29yZHNbMF0sXG4gICAgICAgICAgLi4ucmVjb3Jkcy5mbGF0TWFwKChkb21haW4pID0+IFsnLWQnLCBkb21haW5dKSxcbiAgICAgICAgXSxcbiAgICAgICAgbG9nZ2luZzogZWNzLkxvZ0RyaXZlci5hd3NMb2dzKHtcbiAgICAgICAgICBsb2dHcm91cCxcbiAgICAgICAgICBzdHJlYW1QcmVmaXg6IGNlcnRib3RUYWcsXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICApO1xuXG4gICAgY2VydEZpbGVTeXN0ZW0uZ3JhbnQoXG4gICAgICBjZXJ0Ym90VGFza0RlZmluaXRpb24udGFza1JvbGUsXG4gICAgICAnZWxhc3RpY2ZpbGVzeXN0ZW06Q2xpZW50V3JpdGUnLFxuICAgICk7XG4gICAgY2VydGJvdFRhc2tEZWZpbml0aW9uLmFkZFZvbHVtZSh7XG4gICAgICBuYW1lOiAnY2VydFZvbHVtZScsXG4gICAgICBlZnNWb2x1bWVDb25maWd1cmF0aW9uOiB7XG4gICAgICAgIGZpbGVTeXN0ZW1JZDogY2VydEZpbGVTeXN0ZW0uZmlsZVN5c3RlbUlkLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBjZXJ0Ym90Q29udGFpbmVyLmFkZE1vdW50UG9pbnRzKHtcbiAgICAgIHNvdXJjZVZvbHVtZTogJ2NlcnRWb2x1bWUnLFxuICAgICAgY29udGFpbmVyUGF0aDogJy9ldGMvbGV0c2VuY3J5cHQnLFxuICAgICAgcmVhZE9ubHk6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogU2NoZWR1bGUgQ2VydGJvdCBjZXJ0aWZpY2F0ZSBjcmVhdGUvcmVuZXcgb24gU3RlcCBGdW5jdGlvbnNcbiAgICAgKiBTZW5kcyBlbWFpbCBub3RpZmljYXRpb24gb24gY2VydGJvdCBmYWlsdXJlXG4gICAgICovXG4gICAgY29uc3QgdG9waWMgPSBuZXcgVG9waWModGhpcywgJ1RvcGljJyk7XG4gICAgbmV3IFN1YnNjcmlwdGlvbih0aGlzLCAnRW1haWxTdWJzY3JpcHRpb24nLCB7XG4gICAgICB0b3BpYzogdG9waWMsXG4gICAgICBwcm90b2NvbDogU3Vic2NyaXB0aW9uUHJvdG9jb2wuRU1BSUwsXG4gICAgICBlbmRwb2ludDogcHJvcHMuZW1haWwsXG4gICAgfSk7XG5cbiAgICBjb25zdCBjZXJ0Ym90UnVuVGFzayA9IG5ldyBzZm5fdGFza3MuRWNzUnVuVGFzayh0aGlzLCAnQ3JlYXRlQ2VydGlmaWNhdGUnLCB7XG4gICAgICBjbHVzdGVyOiBjbHVzdGVyLFxuICAgICAgdGFza0RlZmluaXRpb246IGNlcnRib3RUYXNrRGVmaW5pdGlvbixcbiAgICAgIGxhdW5jaFRhcmdldDogbmV3IHNmbl90YXNrcy5FY3NFYzJMYXVuY2hUYXJnZXQoKSxcbiAgICAgIGludGVncmF0aW9uUGF0dGVybjogc2ZuLkludGVncmF0aW9uUGF0dGVybi5SVU5fSk9CLFxuICAgIH0pO1xuICAgIGNlcnRib3RSdW5UYXNrLmFkZENhdGNoKFxuICAgICAgbmV3IHNmbl90YXNrcy5TbnNQdWJsaXNoKHRoaXMsICdTZW5kRW1haWxPbkZhaWx1cmUnLCB7XG4gICAgICAgIHRvcGljOiB0b3BpYyxcbiAgICAgICAgbWVzc2FnZTogc2ZuLlRhc2tJbnB1dC5mcm9tSnNvblBhdGhBdCgnJCcpLFxuICAgICAgfSkubmV4dChuZXcgc2ZuLkZhaWwodGhpcywgJ0ZhaWwnKSksXG4gICAgKTtcbiAgICBjZXJ0Ym90UnVuVGFzay5hZGRSZXRyeSh7XG4gICAgICBpbnRlcnZhbDogbGliLkR1cmF0aW9uLnNlY29uZHMoMjApLFxuICAgIH0pO1xuICAgIGNvbnN0IGNlcnRib3RTdGF0ZU1hY2hpbmUgPSBuZXcgc2ZuLlN0YXRlTWFjaGluZSh0aGlzLCAnU3RhdGVNYWNoaW5lJywge1xuICAgICAgZGVmaW5pdGlvbjogY2VydGJvdFJ1blRhc2ssXG4gICAgfSk7XG5cbiAgICBuZXcgUnVsZSh0aGlzLCAnQ2VydGJvdFNjaGVkdWxlUnVsZScsIHtcbiAgICAgIHNjaGVkdWxlOiBTY2hlZHVsZS5yYXRlKFxuICAgICAgICBsaWIuRHVyYXRpb24uZGF5cyhwcm9wcy5jZXJ0Ym90U2NoZWR1bGVJbnRlcnZhbCA/PyA2MCksXG4gICAgICApLFxuICAgICAgdGFyZ2V0czogW25ldyBTZm5TdGF0ZU1hY2hpbmUoY2VydGJvdFN0YXRlTWFjaGluZSldLFxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogU2VydmVyIEVDUyB0YXNrXG4gICAgICovXG4gICAgY29uc3Qgc2VydmVyVGFza0RlZmluaXRpb24gPVxuICAgICAgcHJvcHMuc2VydmVyVGFza0RlZmluaXRpb24gPz8gdGhpcy5zYW1wbGVTZXZlclRhc2socmVjb3JkcywgbG9nR3JvdXApO1xuICAgIGNlcnRGaWxlU3lzdGVtLmdyYW50KFxuICAgICAgc2VydmVyVGFza0RlZmluaXRpb24udGFza1JvbGUsXG4gICAgICAnZWxhc3RpY2ZpbGVzeXN0ZW06Q2xpZW50TW91bnQnLFxuICAgICk7XG4gICAgc2VydmVyVGFza0RlZmluaXRpb24uYWRkVm9sdW1lKHtcbiAgICAgIG5hbWU6ICdjZXJ0Vm9sdW1lJyxcbiAgICAgIGVmc1ZvbHVtZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgZmlsZVN5c3RlbUlkOiBjZXJ0RmlsZVN5c3RlbS5maWxlU3lzdGVtSWQsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHNlcnZlclRhc2tEZWZpbml0aW9uLmRlZmF1bHRDb250YWluZXI/LmFkZE1vdW50UG9pbnRzKHtcbiAgICAgIHNvdXJjZVZvbHVtZTogJ2NlcnRWb2x1bWUnLFxuICAgICAgY29udGFpbmVyUGF0aDogJy9ldGMvbGV0c2VuY3J5cHQnLFxuICAgICAgcmVhZE9ubHk6IHRydWUsXG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBBV1MgY2xpIGNvbnRhaW5lciB0byBleGVjdXRlIGNlcnRib3Qgc2ZuIGJlZm9yZSB0aGUgZGVmYXVsdCBjb250YWluZXIgc3RhcnR1cC5cbiAgICAgKi9cbiAgICBzZXJ2ZXJUYXNrRGVmaW5pdGlvbi5kZWZhdWx0Q29udGFpbmVyPy5hZGRDb250YWluZXJEZXBlbmRlbmNpZXMoe1xuICAgICAgY29udGFpbmVyOiBzZXJ2ZXJUYXNrRGVmaW5pdGlvbi5hZGRDb250YWluZXIoJ0FXU0NsaUNvbnRhaW5lcicsIHtcbiAgICAgICAgaW1hZ2U6IGVjcy5Db250YWluZXJJbWFnZS5mcm9tUmVnaXN0cnkoYGFtYXpvbi9hd3MtY2xpOiR7YXdzQ2xpVGFnfWApLFxuICAgICAgICBjb250YWluZXJOYW1lOiAnYXdzLWNsaScsXG4gICAgICAgIG1lbW9yeVJlc2VydmF0aW9uTWlCOiA2NCxcbiAgICAgICAgZW50cnlQb2ludDogWycvYmluL2Jhc2gnLCAnLWMnXSxcbiAgICAgICAgY29tbWFuZDogW1xuICAgICAgICAgIGBzZXQgLWV1eFxuICAgICAgICAgIGF3cyBjb25maWd1cmUgc2V0IHJlZ2lvbiAke2NlcnRib3RTdGF0ZU1hY2hpbmUuZW52LnJlZ2lvbn0gJiYgXFxcXFxuICAgICAgICAgIGF3cyBjb25maWd1cmUgc2V0IG91dHB1dCB0ZXh0ICYmIFxcXFxcbiAgICAgICAgICBFWEVDVVRJT05fQVJOPSQoYXdzIHN0ZXBmdW5jdGlvbnMgc3RhcnQtZXhlY3V0aW9uIC0tc3RhdGUtbWFjaGluZS1hcm4gJHtjZXJ0Ym90U3RhdGVNYWNoaW5lLnN0YXRlTWFjaGluZUFybn0gLS1xdWVyeSBleGVjdXRpb25Bcm4pICYmIFxcXFxcbiAgICAgICAgICB1bnRpbCBbICQoYXdzIHN0ZXBmdW5jdGlvbnMgZGVzY3JpYmUtZXhlY3V0aW9uIC0tZXhlY3V0aW9uLWFybiBcIiRFWEVDVVRJT05fQVJOXCIgLS1xdWVyeSBzdGF0dXMpICE9IFJVTk5JTkcgXTtcbiAgICAgICAgICBkb1xuICAgICAgICAgICAgZWNobyBcIldhaXRpbmcgZm9yICRFWEVDVVRJT05fQVJOXCJcbiAgICAgICAgICAgIHNsZWVwIDEwXG4gICAgICAgICAgZG9uZWAsXG4gICAgICAgIF0sXG4gICAgICAgIGVzc2VudGlhbDogZmFsc2UsXG4gICAgICAgIGxvZ2dpbmc6IGVjcy5Mb2dEcml2ZXIuYXdzTG9ncyh7XG4gICAgICAgICAgbG9nR3JvdXA6IGxvZ0dyb3VwLFxuICAgICAgICAgIHN0cmVhbVByZWZpeDogYXdzQ2xpVGFnLFxuICAgICAgICB9KSxcbiAgICAgIH0pLFxuICAgICAgY29uZGl0aW9uOiBlY3MuQ29udGFpbmVyRGVwZW5kZW5jeUNvbmRpdGlvbi5DT01QTEVURSxcbiAgICB9KTtcbiAgICBjZXJ0Ym90U3RhdGVNYWNoaW5lLmdyYW50RXhlY3V0aW9uKFxuICAgICAgc2VydmVyVGFza0RlZmluaXRpb24udGFza1JvbGUsXG4gICAgICAnc3RhdGVzOkRlc2NyaWJlRXhlY3V0aW9uJyxcbiAgICApO1xuICAgIGNlcnRib3RTdGF0ZU1hY2hpbmUuZ3JhbnRTdGFydEV4ZWN1dGlvbihzZXJ2ZXJUYXNrRGVmaW5pdGlvbi50YXNrUm9sZSk7XG5cbiAgICBuZXcgZWNzLkVjMlNlcnZpY2UodGhpcywgJ1NlcnZpY2UnLCB7XG4gICAgICBjbHVzdGVyOiBjbHVzdGVyLFxuICAgICAgdGFza0RlZmluaXRpb246IHNlcnZlclRhc2tEZWZpbml0aW9uLFxuICAgICAgZGVzaXJlZENvdW50OiAxLFxuICAgICAgbWluSGVhbHRoeVBlcmNlbnQ6IDAsXG4gICAgICBtYXhIZWFsdGh5UGVyY2VudDogMTAwLFxuICAgICAgY2lyY3VpdEJyZWFrZXI6IHtcbiAgICAgICAgcm9sbGJhY2s6IHRydWUsXG4gICAgICB9LFxuICAgICAgZW5hYmxlRXhlY3V0ZUNvbW1hbmQ6IHRydWUsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHNhbXBsZVNldmVyVGFzayhcbiAgICByZWNvcmRzOiBzdHJpbmdbXSxcbiAgICBsb2dHcm91cDogSUxvZ0dyb3VwLFxuICApOiBlY3MuRWMyVGFza0RlZmluaXRpb24ge1xuICAgIGNvbnN0IG5naW54VGFza0RlZmluaXRpb24gPSBuZXcgZWNzLkVjMlRhc2tEZWZpbml0aW9uKFxuICAgICAgdGhpcyxcbiAgICAgICdOZ2lueFRhc2tEZWZpbml0aW9uJyxcbiAgICApO1xuICAgIGNvbnN0IG5naW54Q29udGFpbmVyID0gbmdpbnhUYXNrRGVmaW5pdGlvbi5hZGRDb250YWluZXIoJ05naW54Q29udGFpbmVyJywge1xuICAgICAgaW1hZ2U6IGVjcy5Db250YWluZXJJbWFnZS5mcm9tQXNzZXQoXG4gICAgICAgIHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi9jb250YWluZXJzL25naW54LXByb3h5JyksXG4gICAgICApLFxuICAgICAgY29udGFpbmVyTmFtZTogJ25naW54JyxcbiAgICAgIG1lbW9yeVJlc2VydmF0aW9uTWlCOiA2NCxcbiAgICAgIGVzc2VudGlhbDogdHJ1ZSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIFNFUlZFUl9OQU1FOiByZWNvcmRzLmpvaW4oJyAnKSxcbiAgICAgICAgQ0VSVF9OQU1FOiByZWNvcmRzWzBdLFxuICAgICAgfSxcbiAgICAgIGxvZ2dpbmc6IGVjcy5Mb2dEcml2ZXJzLmF3c0xvZ3Moe1xuICAgICAgICBsb2dHcm91cDogbG9nR3JvdXAsXG4gICAgICAgIHN0cmVhbVByZWZpeDogJ25naW54LXByb3h5JyxcbiAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgbmdpbnhDb250YWluZXIuYWRkUG9ydE1hcHBpbmdzKFxuICAgICAge1xuICAgICAgICBob3N0UG9ydDogODAsXG4gICAgICAgIGNvbnRhaW5lclBvcnQ6IDgwLFxuICAgICAgICBwcm90b2NvbDogZWNzLlByb3RvY29sLlRDUCxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGhvc3RQb3J0OiA0NDMsXG4gICAgICAgIGNvbnRhaW5lclBvcnQ6IDQ0MyxcbiAgICAgICAgcHJvdG9jb2w6IGVjcy5Qcm90b2NvbC5UQ1AsXG4gICAgICB9LFxuICAgICk7XG5cbiAgICByZXR1cm4gbmdpbnhUYXNrRGVmaW5pdGlvbjtcbiAgfVxufVxuIl19
|
package/package.json
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "low-cost-ecs",
|
|
3
|
+
"description": "Easy and low-cost ECS on EC2 server without a load balancer",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/rajyan/low-cost-ecs.git"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "npx projen build",
|
|
10
|
+
"bump": "npx projen bump",
|
|
11
|
+
"clobber": "npx projen clobber",
|
|
12
|
+
"compat": "npx projen compat",
|
|
13
|
+
"compile": "npx projen compile",
|
|
14
|
+
"default": "npx projen default",
|
|
15
|
+
"docgen": "npx projen docgen",
|
|
16
|
+
"eject": "npx projen eject",
|
|
17
|
+
"eslint": "npx projen eslint",
|
|
18
|
+
"package": "npx projen package",
|
|
19
|
+
"package-all": "npx projen package-all",
|
|
20
|
+
"package:js": "npx projen package:js",
|
|
21
|
+
"package:python": "npx projen package:python",
|
|
22
|
+
"post-compile": "npx projen post-compile",
|
|
23
|
+
"post-upgrade": "npx projen post-upgrade",
|
|
24
|
+
"pre-compile": "npx projen pre-compile",
|
|
25
|
+
"release": "npx projen release",
|
|
26
|
+
"test": "npx projen test",
|
|
27
|
+
"test:update": "npx projen test:update",
|
|
28
|
+
"test:watch": "npx projen test:watch",
|
|
29
|
+
"unbump": "npx projen unbump",
|
|
30
|
+
"upgrade": "npx projen upgrade",
|
|
31
|
+
"watch": "npx projen watch",
|
|
32
|
+
"projen": "npx projen"
|
|
33
|
+
},
|
|
34
|
+
"author": {
|
|
35
|
+
"name": "Yohta Kimura",
|
|
36
|
+
"email": "kitakita7617@gmail.com",
|
|
37
|
+
"organization": false
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/jest": "^27",
|
|
41
|
+
"@types/node": "^14",
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "^5",
|
|
43
|
+
"@typescript-eslint/parser": "^5",
|
|
44
|
+
"aws-cdk": "^2.39.0",
|
|
45
|
+
"aws-cdk-lib": "2.37.0",
|
|
46
|
+
"constructs": "10.0.5",
|
|
47
|
+
"eslint": "8.22.0",
|
|
48
|
+
"eslint-import-resolver-node": "^0.3.6",
|
|
49
|
+
"eslint-import-resolver-typescript": "^3.5.0",
|
|
50
|
+
"eslint-plugin-import": "^2.26.0",
|
|
51
|
+
"jest": "^27",
|
|
52
|
+
"jest-junit": "^13",
|
|
53
|
+
"jsii": "^1.65.0",
|
|
54
|
+
"jsii-diff": "^1.65.0",
|
|
55
|
+
"jsii-docgen": "^7.0.73",
|
|
56
|
+
"jsii-pacmak": "^1.65.0",
|
|
57
|
+
"json-schema": "^0.4.0",
|
|
58
|
+
"npm-check-updates": "^15",
|
|
59
|
+
"projen": "^0.61.30",
|
|
60
|
+
"standard-version": "^9",
|
|
61
|
+
"ts-jest": "^27",
|
|
62
|
+
"ts-node": "^10.9.1",
|
|
63
|
+
"typescript": "~4.7.4"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"aws-cdk-lib": "^2.37.0",
|
|
67
|
+
"constructs": "^10.0.5"
|
|
68
|
+
},
|
|
69
|
+
"keywords": [
|
|
70
|
+
"cdk",
|
|
71
|
+
"certbot",
|
|
72
|
+
"ecs",
|
|
73
|
+
"loadbalancer",
|
|
74
|
+
"route53",
|
|
75
|
+
"stepfunctions"
|
|
76
|
+
],
|
|
77
|
+
"main": "lib/index.js",
|
|
78
|
+
"license": "MIT",
|
|
79
|
+
"version": "0.0.6",
|
|
80
|
+
"jest": {
|
|
81
|
+
"testMatch": [
|
|
82
|
+
"<rootDir>/src/**/__tests__/**/*.ts?(x)",
|
|
83
|
+
"<rootDir>/(test|src)/**/*(*.)@(spec|test).ts?(x)"
|
|
84
|
+
],
|
|
85
|
+
"clearMocks": true,
|
|
86
|
+
"collectCoverage": true,
|
|
87
|
+
"coverageReporters": [
|
|
88
|
+
"json",
|
|
89
|
+
"lcov",
|
|
90
|
+
"clover",
|
|
91
|
+
"cobertura",
|
|
92
|
+
"text"
|
|
93
|
+
],
|
|
94
|
+
"coverageDirectory": "coverage",
|
|
95
|
+
"coveragePathIgnorePatterns": [
|
|
96
|
+
"/node_modules/"
|
|
97
|
+
],
|
|
98
|
+
"testPathIgnorePatterns": [
|
|
99
|
+
"/node_modules/"
|
|
100
|
+
],
|
|
101
|
+
"watchPathIgnorePatterns": [
|
|
102
|
+
"/node_modules/"
|
|
103
|
+
],
|
|
104
|
+
"reporters": [
|
|
105
|
+
"default",
|
|
106
|
+
[
|
|
107
|
+
"jest-junit",
|
|
108
|
+
{
|
|
109
|
+
"outputDirectory": "test-reports"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
],
|
|
113
|
+
"preset": "ts-jest",
|
|
114
|
+
"globals": {
|
|
115
|
+
"ts-jest": {
|
|
116
|
+
"tsconfig": "tsconfig.dev.json"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"types": "lib/index.d.ts",
|
|
121
|
+
"stability": "experimental",
|
|
122
|
+
"jsii": {
|
|
123
|
+
"outdir": "dist",
|
|
124
|
+
"targets": {
|
|
125
|
+
"python": {
|
|
126
|
+
"distName": "low-cost-ecs",
|
|
127
|
+
"module": "low_cost_ecs"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"tsc": {
|
|
131
|
+
"outDir": "lib",
|
|
132
|
+
"rootDir": "src"
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"resolutions": {
|
|
136
|
+
"@types/prettier": "2.6.0"
|
|
137
|
+
},
|
|
138
|
+
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"."
|
|
139
|
+
}
|
package/todo.md
ADDED