@glicogh/healthcare-cdk 0.1.87 → 0.1.89
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/.env.example +4 -0
- package/README.md +59 -2
- package/dist/@types/common.d.ts +1 -1
- package/dist/@types/common.js +3 -1
- package/dist/constructs/migration-scripts-runner.d.ts +19 -0
- package/dist/constructs/migration-scripts-runner.js +52 -0
- package/dist/constructs/migration-state-machine.d.ts +40 -0
- package/dist/constructs/migration-state-machine.js +223 -0
- package/dist/lib/microservice-clickhouse.d.ts +5 -0
- package/dist/lib/microservice-clickhouse.js +42 -0
- package/dist/lib/microservice-migration.js +39 -3
- package/dist/lib/microservice-network.js +13 -1
- package/dist/scripts/post-deployment-clickhouse.sh +240 -0
- package/dist/util/constants.d.ts +2 -1
- package/dist/util/constants.js +2 -1
- package/dist/util/initCdkStack.js +35 -16
- package/dist/util/migration.d.ts +5 -1
- package/dist/util/migration.js +58 -42
- package/package.json +2 -1
- package/scripts/post-deployment-clickhouse.sh +240 -0
package/.env.example
CHANGED
|
@@ -13,6 +13,10 @@ EC2_MYSQL_INSTANCE_TYPE=t4g.nano
|
|
|
13
13
|
EC2_MYSQL_INSTANCE_STORAGE_SIZE=10
|
|
14
14
|
EC2_MYSQL_INSTANCE_STORAGE_TYPE=gp3
|
|
15
15
|
|
|
16
|
+
EC2_CLICKHOUSE_INSTANCE_TYPE=t4g.nano
|
|
17
|
+
EC2_CLICKHOUSE_INSTANCE_STORAGE_SIZE=50
|
|
18
|
+
EC2_CLICKHOUSE_INSTANCE_STORAGE_TYPE=gp3
|
|
19
|
+
|
|
16
20
|
EC2_API_GATEWAY_INSTANCE_TYPE=t4g.nano
|
|
17
21
|
EC2_API_GATEWAY_INSTANCE_STORAGE_SIZE=
|
|
18
22
|
EC2_API_GATEWAY_INSTANCE_STORAGE_TYPE=gp3
|
package/README.md
CHANGED
|
@@ -77,6 +77,7 @@ The output looks like this
|
|
|
77
77
|
MicroserviceNetwork
|
|
78
78
|
MicroserviceRedis
|
|
79
79
|
MicroserviceMySQL
|
|
80
|
+
MicroserviceClickHouse
|
|
80
81
|
```
|
|
81
82
|
|
|
82
83
|
## Running the CDK
|
|
@@ -89,13 +90,69 @@ The following stack are meant to be deployed once and shared across the microser
|
|
|
89
90
|
- MicroserviceInfraAuth
|
|
90
91
|
- MicroserviceRedis
|
|
91
92
|
- MicroserviceMySQL
|
|
93
|
+
- MicroserviceClickHouse
|
|
94
|
+
- MicroserviceMigration
|
|
92
95
|
|
|
93
|
-
The only required option for these
|
|
96
|
+
The only required option for these stacks is `env`. To deploy a single shared stack, pass its `service` value:
|
|
97
|
+
|
|
98
|
+
| Stack | `service` |
|
|
99
|
+
| ---------------------- | ------------ |
|
|
100
|
+
| MicroserviceNetwork | `network` |
|
|
101
|
+
| MicroserviceInfraAuth | `infra-auth` |
|
|
102
|
+
| MicroserviceRedis | `redis` |
|
|
103
|
+
| MicroserviceMySQL | `mysql` |
|
|
104
|
+
| MicroserviceClickHouse | `clickhouse` |
|
|
105
|
+
| MicroserviceMigration | `migration` |
|
|
106
|
+
|
|
107
|
+
For example, to deploy `MicroserviceNetwork` in the UAT environment, you would run the command
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
cdk --profile glicogh-uat --context env=uat --context service=network deploy
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Only the selected stack is synthesized, so unrelated stacks (and their code assets, such as the migration Lambdas) are not bundled. Omitting `service` synthesizes and deploys all shared stacks. Alternatively, when deploying by stack name (`cdk --context env=uat deploy MicroserviceNetwork`), pass `--exclusively` to `synth`/`deploy`/`diff` to skip bundling unrelated stacks.
|
|
114
|
+
|
|
115
|
+
### Migration orchestrator (MicroserviceMigration)
|
|
116
|
+
|
|
117
|
+
`MicroserviceMigration` bundles the migration producer/consumer Lambdas (from the sibling `migration/lambdas` directory), the `migration-queue.fifo` queue, a `migration-verifier` Lambda, an S3 artifacts bucket, a one-shot ECS Fargate scripts runner, and the `migration-orchestrator` Step Function (`cdk/constructs/migration-state-machine.ts`). Invoking the state machine runs the migration runbook end-to-end:
|
|
118
|
+
|
|
119
|
+
- **Scripts (runbook Steps 1–4)** run as one-shot ECS Fargate tasks from the migration repo's `Dockerfile` (entrypoint dispatches `restore` / `migrations` / `diseases` / `claim-batches` / `reset`). The restore task syncs the legacy dump from S3 first; no 15-minute Lambda cap.
|
|
120
|
+
- **Migratables (Steps 5–16)** loop the producer Lambda until the response reports `endReached: true`, then wait for the SQS queue to drain (`ApproximateNumberOfMessages` + `NotVisible` = 0) before the next dependency step. Tier 0 (users, providers, insured, tpa, plans) runs as a `Parallel`.
|
|
121
|
+
- **Every resource gets a retry pass** (`fromStart: true, skipMigrated: true`) after the first pass + drain, recovering records dropped by transient service failures.
|
|
122
|
+
- **Verification** invokes the verifier Lambda, which writes `runs/<execution-name>/summary.json` (migrated counts, source counts, API totals) to the artifacts bucket.
|
|
123
|
+
|
|
124
|
+
**Prerequisites**: deploy the shared stacks (the migration stack alone with `cdk --profile glicogh-uat --context env=uat --context service=migration deploy`); upload the legacy dump to the artifacts bucket (`glicogh-healthcare-migration-<env>-<account>`):
|
|
94
125
|
|
|
95
126
|
```
|
|
96
|
-
|
|
127
|
+
aws s3 sync data/legacy-backup s3://glicogh-healthcare-migration-uat-825765383017/backups/<runId>/
|
|
97
128
|
```
|
|
98
129
|
|
|
130
|
+
**Start an execution** (all input fields are required; `fromStep` uses the step ids below, `""` = full run):
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"backupS3Uri": "s3://glicogh-healthcare-migration-uat-825765383017/backups/<runId>/",
|
|
135
|
+
"fresh": false,
|
|
136
|
+
"skipPhotos": false,
|
|
137
|
+
"fromStep": ""
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
aws stepfunctions start-execution \
|
|
143
|
+
--state-machine-arn <state-machine-arn> \
|
|
144
|
+
--name <runId> \
|
|
145
|
+
--input file://input.json
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Step ids for `fromStep`: `fresh-reset`, `restore`, `migrations`, `diseases`, `claim-batches`, `product-sources`, `product-categories`, `products`, `categories`, `coverage-groups`, `tier0`, `product-pricing`, `policies`, `benefits`, `plans-rewire`, `beneficiaries-principals`, `beneficiaries-dependants`, `beneficiary-photos`, `claims`.
|
|
149
|
+
|
|
150
|
+
**Pause/resume**: every step is idempotent and cursor-backed — stop the execution and re-invoke later (optionally with `fromStep`). Completed resources no-op on the first producer invocation (`endReached` immediately). Guards fail the execution instead of looping forever: 2,000 producer invocations per pass, 600 drain checks (5-minute interval). Execution timeout 7 days.
|
|
151
|
+
|
|
152
|
+
**Monitoring**: Step Functions execution history; state-machine logs at `/aws/vendedlogs/states/migration-orchestrator`; ECS task logs under `/aws/ecs/migration-scripts`; the verifier summary in S3.
|
|
153
|
+
|
|
154
|
+
**Notes**: the consumer's reserved concurrency is set to `max(50, MIGRATION_QUEUE_SHARDS)` so claims FIFO shards run in parallel. `fresh: true` truncates `migrated`/`disease_lookup`/`claim_batches` and clears the `glico_healthcare_migration:*` Redis cursors before restoring; the restore task re-imports all tables per run (container-local tracking). Secure envs (`DB_PASSWORD`, `MIGRATION_API_KEY`) are injected into the ECS task from SSM.
|
|
155
|
+
|
|
99
156
|
### Pipeline-based stack
|
|
100
157
|
|
|
101
158
|
The following stack on the other hand, are meant to deploy a new set of resources on each CDK deployment. These can also be thought of as the stack that have a GIT repository.
|
package/dist/@types/common.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type BuildConfig = {
|
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
18
|
export type Microservice = 'account' | 'plan' | 'policy' | 'claims' | 'notification' | 'reporting';
|
|
19
|
-
export type OtherCDKService = 'network' | 'api-gateway' | 'redis' | 'mysql' | 'portal' | 'migration';
|
|
19
|
+
export type OtherCDKService = 'network' | 'infra-auth' | 'api-gateway' | 'redis' | 'mysql' | 'clickhouse' | 'portal' | 'migration';
|
|
20
20
|
export declare const MicroserviceEnum: Record<Microservice, Microservice>;
|
|
21
21
|
export declare const MicroserviceList: Microservice[];
|
|
22
22
|
export declare const LaravelBasedServiceList: ("account" | "plan" | "policy" | "claims" | "reporting")[];
|
package/dist/@types/common.js
CHANGED
|
@@ -13,11 +13,13 @@ exports.MicroserviceList = Object.values(exports.MicroserviceEnum);
|
|
|
13
13
|
exports.LaravelBasedServiceList = exports.MicroserviceList.filter((i) => i !== 'notification');
|
|
14
14
|
exports.OtherCDKServiceEnum = {
|
|
15
15
|
network: 'network',
|
|
16
|
+
'infra-auth': 'infra-auth',
|
|
16
17
|
'api-gateway': 'api-gateway',
|
|
17
18
|
redis: 'redis',
|
|
18
19
|
mysql: 'mysql',
|
|
20
|
+
clickhouse: 'clickhouse',
|
|
19
21
|
portal: 'portal',
|
|
20
22
|
migration: 'migration',
|
|
21
23
|
};
|
|
22
24
|
exports.OtherCDKServiceList = Object.values(exports.OtherCDKServiceEnum);
|
|
23
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vQHR5cGVzL2NvbW1vbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFxQmEsUUFBQSxnQkFBZ0IsR0FBdUM7SUFDbEUsT0FBTyxFQUFFLFNBQVM7SUFDbEIsSUFBSSxFQUFFLE1BQU07SUFDWixNQUFNLEVBQUUsUUFBUTtJQUNoQixZQUFZLEVBQUUsY0FBYztJQUM1QixTQUFTLEVBQUUsV0FBVztJQUN0QixNQUFNLEVBQUUsUUFBUTtDQUNqQixDQUFDO0FBRVcsUUFBQSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLHdCQUFnQixDQUFDLENBQUM7QUFFbkQsUUFBQSx1QkFBdUIsR0FBRyx3QkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxjQUFjLENBQUMsQ0FBQztBQUUvRSxRQUFBLG1CQUFtQixHQUE2QztJQUMzRSxPQUFPLEVBQUUsU0FBUztJQUNsQixZQUFZLEVBQUUsWUFBWTtJQUMxQixhQUFhLEVBQUUsYUFBYTtJQUM1QixLQUFLLEVBQUUsT0FBTztJQUNkLEtBQUssRUFBRSxPQUFPO0lBQ2QsVUFBVSxFQUFFLFlBQVk7SUFDeEIsTUFBTSxFQUFFLFFBQVE7SUFDaEIsU0FBUyxFQUFFLFdBQVc7Q0FDdkIsQ0FBQztBQUVXLFFBQUEsbUJBQW1CLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQywyQkFBbUIsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHR5cGUgRW52TmFtZSA9ICd1YXQnIHwgJ3Byb2QnO1xuZXhwb3J0IHR5cGUgUmVwb0JyYW5jaCA9ICdtYXN0ZXInIHwgJ3JlbGVhc2UnO1xuZXhwb3J0IHR5cGUgQnVpbGRDb25maWcgPSB7XG4gIGFwcE5hbWU6IHN0cmluZztcbiAgYXBwVmVyc2lvbjogc3RyaW5nO1xuICBidWlsZElkOiBzdHJpbmc7XG4gIGZvcm1hdHRlZEJ1aWxkSWQ6IHN0cmluZztcbiAgZW52TmFtZTogRW52TmFtZTtcbiAgZW52UGF0aDogc3RyaW5nO1xuICBzZXJ2aWNlTmFtZTogTWljcm9zZXJ2aWNlIHwgT3RoZXJDREtTZXJ2aWNlO1xuICBicmFuY2g/OiBzdHJpbmc7XG4gIGNvbXBhbnlOYW1lOiBzdHJpbmc7XG4gIGF3czoge1xuICAgIGFjY291bnQ6IHN0cmluZztcbiAgICByZWdpb246IHN0cmluZztcbiAgfTtcbn07XG5leHBvcnQgdHlwZSBNaWNyb3NlcnZpY2UgPSAnYWNjb3VudCcgfCAncGxhbicgfCAncG9saWN5JyB8ICdjbGFpbXMnIHwgJ25vdGlmaWNhdGlvbicgfCAncmVwb3J0aW5nJztcblxuZXhwb3J0IHR5cGUgT3RoZXJDREtTZXJ2aWNlID0gJ25ldHdvcmsnIHwgJ2luZnJhLWF1dGgnIHwgJ2FwaS1nYXRld2F5JyB8ICdyZWRpcycgfCAnbXlzcWwnIHwgJ2NsaWNraG91c2UnIHwgJ3BvcnRhbCcgfCAnbWlncmF0aW9uJztcblxuZXhwb3J0IGNvbnN0IE1pY3Jvc2VydmljZUVudW06IFJlY29yZDxNaWNyb3NlcnZpY2UsIE1pY3Jvc2VydmljZT4gPSB7XG4gIGFjY291bnQ6ICdhY2NvdW50JyxcbiAgcGxhbjogJ3BsYW4nLFxuICBwb2xpY3k6ICdwb2xpY3knLFxuICBub3RpZmljYXRpb246ICdub3RpZmljYXRpb24nLFxuICByZXBvcnRpbmc6ICdyZXBvcnRpbmcnLFxuICBjbGFpbXM6ICdjbGFpbXMnLFxufTtcblxuZXhwb3J0IGNvbnN0IE1pY3Jvc2VydmljZUxpc3QgPSBPYmplY3QudmFsdWVzKE1pY3Jvc2VydmljZUVudW0pO1xuXG5leHBvcnQgY29uc3QgTGFyYXZlbEJhc2VkU2VydmljZUxpc3QgPSBNaWNyb3NlcnZpY2VMaXN0LmZpbHRlcigoaSkgPT4gaSAhPT0gJ25vdGlmaWNhdGlvbicpO1xuXG5leHBvcnQgY29uc3QgT3RoZXJDREtTZXJ2aWNlRW51bTogUmVjb3JkPE90aGVyQ0RLU2VydmljZSwgT3RoZXJDREtTZXJ2aWNlPiA9IHtcbiAgbmV0d29yazogJ25ldHdvcmsnLFxuICAnaW5mcmEtYXV0aCc6ICdpbmZyYS1hdXRoJyxcbiAgJ2FwaS1nYXRld2F5JzogJ2FwaS1nYXRld2F5JyxcbiAgcmVkaXM6ICdyZWRpcycsXG4gIG15c3FsOiAnbXlzcWwnLFxuICBjbGlja2hvdXNlOiAnY2xpY2tob3VzZScsXG4gIHBvcnRhbDogJ3BvcnRhbCcsXG4gIG1pZ3JhdGlvbjogJ21pZ3JhdGlvbicsXG59O1xuXG5leHBvcnQgY29uc3QgT3RoZXJDREtTZXJ2aWNlTGlzdCA9IE9iamVjdC52YWx1ZXMoT3RoZXJDREtTZXJ2aWNlRW51bSk7XG5cbmV4cG9ydCB0eXBlIFJlcG9VcmxzID0geyBba2V5IGluIEJ1aWxkQ29uZmlnWydzZXJ2aWNlTmFtZSddXT86IHN0cmluZyB9O1xuZXhwb3J0IHR5cGUgUmVwb0JyYW5jaGVzID0geyBba2V5IGluIEVudk5hbWVdOiBSZXBvQnJhbmNoIH07XG4iXX0=
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
3
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
4
|
+
import { Construct } from 'constructs';
|
|
5
|
+
export interface MigrationScriptsRunnerProps {
|
|
6
|
+
vpc: ec2.IVpc;
|
|
7
|
+
artifactsBucket: s3.IBucket;
|
|
8
|
+
backupPrefix?: string;
|
|
9
|
+
cpu?: number;
|
|
10
|
+
memoryLimitMiB?: number;
|
|
11
|
+
ephemeralStorageGiB?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class MigrationScriptsRunner extends Construct {
|
|
14
|
+
readonly cluster: ecs.Cluster;
|
|
15
|
+
readonly securityGroup: ec2.SecurityGroup;
|
|
16
|
+
readonly taskDefinition: ecs.FargateTaskDefinition;
|
|
17
|
+
readonly container: ecs.ContainerDefinition;
|
|
18
|
+
constructor(scope: Construct, id: string, props: MigrationScriptsRunnerProps);
|
|
19
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MigrationScriptsRunner = void 0;
|
|
4
|
+
const cdk = require("aws-cdk-lib");
|
|
5
|
+
const ec2 = require("aws-cdk-lib/aws-ec2");
|
|
6
|
+
const ecs = require("aws-cdk-lib/aws-ecs");
|
|
7
|
+
const logs = require("aws-cdk-lib/aws-logs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
const constructs_1 = require("constructs");
|
|
10
|
+
const migration_1 = require("../util/migration");
|
|
11
|
+
// One-shot Fargate tasks that run the migration scripts (restore, migrations,
|
|
12
|
+
// precompute-diseases, precompute-claim-batches, reset) unchanged. The state
|
|
13
|
+
// machine overrides the container command per step.
|
|
14
|
+
class MigrationScriptsRunner extends constructs_1.Construct {
|
|
15
|
+
constructor(scope, id, props) {
|
|
16
|
+
super(scope, id);
|
|
17
|
+
this.cluster = new ecs.Cluster(this, 'Cluster', {
|
|
18
|
+
vpc: props.vpc,
|
|
19
|
+
clusterName: 'migration-scripts',
|
|
20
|
+
});
|
|
21
|
+
this.securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
|
|
22
|
+
vpc: props.vpc,
|
|
23
|
+
securityGroupName: 'Migration-Scripts-SG',
|
|
24
|
+
description: 'Migration scripts ECS tasks',
|
|
25
|
+
allowAllOutbound: true,
|
|
26
|
+
});
|
|
27
|
+
this.taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDefinition', {
|
|
28
|
+
family: 'migration-scripts',
|
|
29
|
+
cpu: props.cpu ?? 4096,
|
|
30
|
+
memoryLimitMiB: props.memoryLimitMiB ?? 8192,
|
|
31
|
+
ephemeralStorageGiB: props.ephemeralStorageGiB ?? 21,
|
|
32
|
+
runtimePlatform: {
|
|
33
|
+
cpuArchitecture: ecs.CpuArchitecture.X86_64,
|
|
34
|
+
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
const { environment, secrets } = (0, migration_1.getEcsEnvs)(cdk.Stack.of(this));
|
|
38
|
+
this.container = this.taskDefinition.addContainer('scripts', {
|
|
39
|
+
containerName: 'scripts',
|
|
40
|
+
image: ecs.ContainerImage.fromAsset(path.resolve('../../migration'), { file: 'Dockerfile' }),
|
|
41
|
+
environment,
|
|
42
|
+
secrets,
|
|
43
|
+
logging: ecs.LogDrivers.awsLogs({
|
|
44
|
+
streamPrefix: 'migration-scripts',
|
|
45
|
+
logRetention: logs.RetentionDays.ONE_MONTH,
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
props.artifactsBucket.grantRead(this.taskDefinition.taskRole, `${props.backupPrefix ?? 'backups'}/*`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.MigrationScriptsRunner = MigrationScriptsRunner;
|
|
52
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLXNjcmlwdHMtcnVubmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vY29uc3RydWN0cy9taWdyYXRpb24tc2NyaXB0cy1ydW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQW1DO0FBQ25DLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFDM0MsNkNBQTZDO0FBRTdDLDZCQUE2QjtBQUM3QiwyQ0FBdUM7QUFDdkMsaURBQStDO0FBVy9DLDhFQUE4RTtBQUM5RSw2RUFBNkU7QUFDN0Usb0RBQW9EO0FBQ3BELE1BQWEsc0JBQXVCLFNBQVEsc0JBQVM7SUFNbkQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFrQztRQUMxRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUU7WUFDOUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHO1lBQ2QsV0FBVyxFQUFFLG1CQUFtQjtTQUNqQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksR0FBRyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsZUFBZSxFQUFFO1lBQ2hFLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRztZQUNkLGlCQUFpQixFQUFFLHNCQUFzQjtZQUN6QyxXQUFXLEVBQUUsNkJBQTZCO1lBQzFDLGdCQUFnQixFQUFFLElBQUk7U0FDdkIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7WUFDMUUsTUFBTSxFQUFFLG1CQUFtQjtZQUMzQixHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBSSxJQUFJO1lBQ3RCLGNBQWMsRUFBRSxLQUFLLENBQUMsY0FBYyxJQUFJLElBQUk7WUFDNUMsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLG1CQUFtQixJQUFJLEVBQUU7WUFDcEQsZUFBZSxFQUFFO2dCQUNmLGVBQWUsRUFBRSxHQUFHLENBQUMsZUFBZSxDQUFDLE1BQU07Z0JBQzNDLHFCQUFxQixFQUFFLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLO2FBQ3ZEO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFBLHNCQUFVLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUVoRSxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRTtZQUMzRCxhQUFhLEVBQUUsU0FBUztZQUN4QixLQUFLLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDO1lBQzVGLFdBQVc7WUFDWCxPQUFPO1lBQ1AsT0FBTyxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO2dCQUM5QixZQUFZLEVBQUUsbUJBQW1CO2dCQUNqQyxZQUFZLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTO2FBQzNDLENBQUM7U0FDSCxDQUFDLENBQUM7UUFFSCxLQUFLLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxHQUFHLEtBQUssQ0FBQyxZQUFZLElBQUksU0FBUyxJQUFJLENBQUMsQ0FBQztJQUN4RyxDQUFDO0NBQ0Y7QUEvQ0Qsd0RBK0NDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGVjMiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGVjcyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWNzJztcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IGdldEVjc0VudnMgfSBmcm9tICcuLi91dGlsL21pZ3JhdGlvbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWlncmF0aW9uU2NyaXB0c1J1bm5lclByb3BzIHtcbiAgdnBjOiBlYzIuSVZwYztcbiAgYXJ0aWZhY3RzQnVja2V0OiBzMy5JQnVja2V0O1xuICBiYWNrdXBQcmVmaXg/OiBzdHJpbmc7XG4gIGNwdT86IG51bWJlcjtcbiAgbWVtb3J5TGltaXRNaUI/OiBudW1iZXI7XG4gIGVwaGVtZXJhbFN0b3JhZ2VHaUI/OiBudW1iZXI7XG59XG5cbi8vIE9uZS1zaG90IEZhcmdhdGUgdGFza3MgdGhhdCBydW4gdGhlIG1pZ3JhdGlvbiBzY3JpcHRzIChyZXN0b3JlLCBtaWdyYXRpb25zLFxuLy8gcHJlY29tcHV0ZS1kaXNlYXNlcywgcHJlY29tcHV0ZS1jbGFpbS1iYXRjaGVzLCByZXNldCkgdW5jaGFuZ2VkLiBUaGUgc3RhdGVcbi8vIG1hY2hpbmUgb3ZlcnJpZGVzIHRoZSBjb250YWluZXIgY29tbWFuZCBwZXIgc3RlcC5cbmV4cG9ydCBjbGFzcyBNaWdyYXRpb25TY3JpcHRzUnVubmVyIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHVibGljIHJlYWRvbmx5IGNsdXN0ZXI6IGVjcy5DbHVzdGVyO1xuICBwdWJsaWMgcmVhZG9ubHkgc2VjdXJpdHlHcm91cDogZWMyLlNlY3VyaXR5R3JvdXA7XG4gIHB1YmxpYyByZWFkb25seSB0YXNrRGVmaW5pdGlvbjogZWNzLkZhcmdhdGVUYXNrRGVmaW5pdGlvbjtcbiAgcHVibGljIHJlYWRvbmx5IGNvbnRhaW5lcjogZWNzLkNvbnRhaW5lckRlZmluaXRpb247XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE1pZ3JhdGlvblNjcmlwdHNSdW5uZXJQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLmNsdXN0ZXIgPSBuZXcgZWNzLkNsdXN0ZXIodGhpcywgJ0NsdXN0ZXInLCB7XG4gICAgICB2cGM6IHByb3BzLnZwYyxcbiAgICAgIGNsdXN0ZXJOYW1lOiAnbWlncmF0aW9uLXNjcmlwdHMnLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZWN1cml0eUdyb3VwID0gbmV3IGVjMi5TZWN1cml0eUdyb3VwKHRoaXMsICdTZWN1cml0eUdyb3VwJywge1xuICAgICAgdnBjOiBwcm9wcy52cGMsXG4gICAgICBzZWN1cml0eUdyb3VwTmFtZTogJ01pZ3JhdGlvbi1TY3JpcHRzLVNHJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnTWlncmF0aW9uIHNjcmlwdHMgRUNTIHRhc2tzJyxcbiAgICAgIGFsbG93QWxsT3V0Ym91bmQ6IHRydWUsXG4gICAgfSk7XG5cbiAgICB0aGlzLnRhc2tEZWZpbml0aW9uID0gbmV3IGVjcy5GYXJnYXRlVGFza0RlZmluaXRpb24odGhpcywgJ1Rhc2tEZWZpbml0aW9uJywge1xuICAgICAgZmFtaWx5OiAnbWlncmF0aW9uLXNjcmlwdHMnLFxuICAgICAgY3B1OiBwcm9wcy5jcHUgPz8gNDA5NixcbiAgICAgIG1lbW9yeUxpbWl0TWlCOiBwcm9wcy5tZW1vcnlMaW1pdE1pQiA/PyA4MTkyLFxuICAgICAgZXBoZW1lcmFsU3RvcmFnZUdpQjogcHJvcHMuZXBoZW1lcmFsU3RvcmFnZUdpQiA/PyAyMSxcbiAgICAgIHJ1bnRpbWVQbGF0Zm9ybToge1xuICAgICAgICBjcHVBcmNoaXRlY3R1cmU6IGVjcy5DcHVBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgICBvcGVyYXRpbmdTeXN0ZW1GYW1pbHk6IGVjcy5PcGVyYXRpbmdTeXN0ZW1GYW1pbHkuTElOVVgsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgeyBlbnZpcm9ubWVudCwgc2VjcmV0cyB9ID0gZ2V0RWNzRW52cyhjZGsuU3RhY2sub2YodGhpcykpO1xuXG4gICAgdGhpcy5jb250YWluZXIgPSB0aGlzLnRhc2tEZWZpbml0aW9uLmFkZENvbnRhaW5lcignc2NyaXB0cycsIHtcbiAgICAgIGNvbnRhaW5lck5hbWU6ICdzY3JpcHRzJyxcbiAgICAgIGltYWdlOiBlY3MuQ29udGFpbmVySW1hZ2UuZnJvbUFzc2V0KHBhdGgucmVzb2x2ZSgnLi4vLi4vbWlncmF0aW9uJyksIHsgZmlsZTogJ0RvY2tlcmZpbGUnIH0pLFxuICAgICAgZW52aXJvbm1lbnQsXG4gICAgICBzZWNyZXRzLFxuICAgICAgbG9nZ2luZzogZWNzLkxvZ0RyaXZlcnMuYXdzTG9ncyh7XG4gICAgICAgIHN0cmVhbVByZWZpeDogJ21pZ3JhdGlvbi1zY3JpcHRzJyxcbiAgICAgICAgbG9nUmV0ZW50aW9uOiBsb2dzLlJldGVudGlvbkRheXMuT05FX01PTlRILFxuICAgICAgfSksXG4gICAgfSk7XG5cbiAgICBwcm9wcy5hcnRpZmFjdHNCdWNrZXQuZ3JhbnRSZWFkKHRoaXMudGFza0RlZmluaXRpb24udGFza1JvbGUsIGAke3Byb3BzLmJhY2t1cFByZWZpeCA/PyAnYmFja3Vwcyd9LypgKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
3
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
4
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
5
|
+
import * as sqs from 'aws-cdk-lib/aws-sqs';
|
|
6
|
+
import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
|
|
7
|
+
import { Construct } from 'constructs';
|
|
8
|
+
export interface MigrationStateMachineProps {
|
|
9
|
+
producer: lambda.IFunction;
|
|
10
|
+
verifier: lambda.IFunction;
|
|
11
|
+
queue: sqs.IQueue;
|
|
12
|
+
cluster: ecs.ICluster;
|
|
13
|
+
taskDefinition: ecs.TaskDefinition;
|
|
14
|
+
container: ecs.ContainerDefinition;
|
|
15
|
+
securityGroup: ec2.ISecurityGroup;
|
|
16
|
+
artifactsBucket: s3.IBucket;
|
|
17
|
+
maxInvocations?: number;
|
|
18
|
+
drainMaxChecks?: number;
|
|
19
|
+
loopWaitSeconds?: number;
|
|
20
|
+
drainWaitSeconds?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare class MigrationStateMachine extends Construct {
|
|
23
|
+
readonly stateMachine: sfn.StateMachine;
|
|
24
|
+
private readonly producer;
|
|
25
|
+
private readonly verifier;
|
|
26
|
+
private readonly queue;
|
|
27
|
+
private readonly cluster;
|
|
28
|
+
private readonly taskDefinition;
|
|
29
|
+
private readonly container;
|
|
30
|
+
private readonly securityGroup;
|
|
31
|
+
private readonly artifactsBucket;
|
|
32
|
+
private readonly maxInvocations;
|
|
33
|
+
private readonly drainMaxChecks;
|
|
34
|
+
private readonly loopWaitSeconds;
|
|
35
|
+
private readonly drainWaitSeconds;
|
|
36
|
+
constructor(scope: Construct, id: string, props: MigrationStateMachineProps);
|
|
37
|
+
private producerPass;
|
|
38
|
+
private resourceStep;
|
|
39
|
+
private ecsStep;
|
|
40
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MigrationStateMachine = void 0;
|
|
4
|
+
const cdk = require("aws-cdk-lib");
|
|
5
|
+
const ec2 = require("aws-cdk-lib/aws-ec2");
|
|
6
|
+
const ecs = require("aws-cdk-lib/aws-ecs");
|
|
7
|
+
const logs = require("aws-cdk-lib/aws-logs");
|
|
8
|
+
const sfn = require("aws-cdk-lib/aws-stepfunctions");
|
|
9
|
+
const tasks = require("aws-cdk-lib/aws-stepfunctions-tasks");
|
|
10
|
+
const constructs_1 = require("constructs");
|
|
11
|
+
// Runs the runbook end-to-end: scripts as one-shot Fargate tasks, SQS
|
|
12
|
+
// migratables as producer loops (until endReached) followed by a queue drain
|
|
13
|
+
// and a skipMigrated retry pass, then the verifier summary.
|
|
14
|
+
class MigrationStateMachine extends constructs_1.Construct {
|
|
15
|
+
constructor(scope, id, props) {
|
|
16
|
+
super(scope, id);
|
|
17
|
+
this.producer = props.producer;
|
|
18
|
+
this.verifier = props.verifier;
|
|
19
|
+
this.queue = props.queue;
|
|
20
|
+
this.cluster = props.cluster;
|
|
21
|
+
this.taskDefinition = props.taskDefinition;
|
|
22
|
+
this.container = props.container;
|
|
23
|
+
this.securityGroup = props.securityGroup;
|
|
24
|
+
this.artifactsBucket = props.artifactsBucket;
|
|
25
|
+
this.maxInvocations = props.maxInvocations ?? 2000;
|
|
26
|
+
this.drainMaxChecks = props.drainMaxChecks ?? 600;
|
|
27
|
+
this.loopWaitSeconds = props.loopWaitSeconds ?? 10;
|
|
28
|
+
this.drainWaitSeconds = props.drainWaitSeconds ?? 300;
|
|
29
|
+
const entries = {};
|
|
30
|
+
const verify = new tasks.LambdaInvoke(this, 'Verify', {
|
|
31
|
+
lambdaFunction: this.verifier,
|
|
32
|
+
payload: sfn.TaskInput.fromObject({
|
|
33
|
+
runId: sfn.JsonPath.stringAt('$$.Execution.Name'),
|
|
34
|
+
bucket: this.artifactsBucket.bucketName,
|
|
35
|
+
key: sfn.JsonPath.format('runs/{}/summary.json', sfn.JsonPath.stringAt('$$.Execution.Name')),
|
|
36
|
+
}),
|
|
37
|
+
payloadResponseOnly: true,
|
|
38
|
+
resultPath: '$.verification',
|
|
39
|
+
});
|
|
40
|
+
const complete = new sfn.Succeed(this, 'Complete');
|
|
41
|
+
verify.next(complete);
|
|
42
|
+
let tail = verify;
|
|
43
|
+
entries['claims'] = this.resourceStep('s16-claims', { resource: 'claims' }, tail);
|
|
44
|
+
tail = entries['claims'];
|
|
45
|
+
const photos = this.resourceStep('s15-beneficiary-photos', { resource: 'beneficiary-photos' }, tail);
|
|
46
|
+
entries['beneficiary-photos'] = photos;
|
|
47
|
+
const photosChoice = new sfn.Choice(this, 'SkipPhotos').when(sfn.Condition.booleanEquals('$.skipPhotos', true), tail).otherwise(photos);
|
|
48
|
+
tail = photosChoice;
|
|
49
|
+
entries['beneficiaries-dependants'] = this.resourceStep('s14b-beneficiaries-dependants', { resource: 'beneficiaries', phase: 'dependants' }, tail);
|
|
50
|
+
tail = entries['beneficiaries-dependants'];
|
|
51
|
+
entries['beneficiaries-principals'] = this.resourceStep('s14a-beneficiaries-principals', { resource: 'beneficiaries', phase: 'principals' }, tail);
|
|
52
|
+
tail = entries['beneficiaries-principals'];
|
|
53
|
+
entries['plans-rewire'] = this.resourceStep('s13b-plans-rewire', { resource: 'plans' }, tail);
|
|
54
|
+
tail = entries['plans-rewire'];
|
|
55
|
+
entries['benefits'] = this.resourceStep('s12-benefits', { resource: 'benefits' }, tail);
|
|
56
|
+
tail = entries['benefits'];
|
|
57
|
+
entries['policies'] = this.resourceStep('s11-policies', { resource: 'policies' }, tail);
|
|
58
|
+
tail = entries['policies'];
|
|
59
|
+
entries['product-pricing'] = this.resourceStep('s10-product-pricing', { resource: 'product-pricing' }, tail);
|
|
60
|
+
tail = entries['product-pricing'];
|
|
61
|
+
const tier0 = new sfn.Parallel(this, 's9-tier0', { resultPath: '$.tier0' });
|
|
62
|
+
for (const resource of ['users', 'providers', 'insured', 'tpa', 'plans']) {
|
|
63
|
+
tier0.branch(sfn.Chain.start(this.resourceStep(`s9-${resource}`, { resource })));
|
|
64
|
+
}
|
|
65
|
+
tier0.next(tail);
|
|
66
|
+
entries['tier0'] = tier0;
|
|
67
|
+
tail = tier0;
|
|
68
|
+
entries['coverage-groups'] = this.resourceStep('s8-coverage-groups', { resource: 'coverage-groups' }, tail);
|
|
69
|
+
tail = entries['coverage-groups'];
|
|
70
|
+
entries['categories'] = this.resourceStep('s7-categories', { resource: 'categories' }, tail);
|
|
71
|
+
tail = entries['categories'];
|
|
72
|
+
entries['products'] = this.resourceStep('s6-products', { resource: 'products' }, tail);
|
|
73
|
+
tail = entries['products'];
|
|
74
|
+
entries['product-categories'] = this.resourceStep('s5b-product-categories', { resource: 'product-categories' }, tail);
|
|
75
|
+
tail = entries['product-categories'];
|
|
76
|
+
entries['product-sources'] = this.resourceStep('s5a-product-sources', { resource: 'product-sources' }, tail);
|
|
77
|
+
tail = entries['product-sources'];
|
|
78
|
+
entries['claim-batches'] = this.ecsStep('s4-claim-batches', 'claim-batches', [], cdk.Duration.hours(2), tail);
|
|
79
|
+
tail = entries['claim-batches'];
|
|
80
|
+
entries['diseases'] = this.ecsStep('s3-disease-lookups', 'diseases', [], cdk.Duration.hours(1), tail);
|
|
81
|
+
tail = entries['diseases'];
|
|
82
|
+
entries['migrations'] = this.ecsStep('s2-migrations', 'migrations', [], cdk.Duration.hours(1), tail);
|
|
83
|
+
tail = entries['migrations'];
|
|
84
|
+
const restore = this.ecsStep('s1-restore', 'restore', [{ name: 'BACKUP_S3_URI', value: sfn.JsonPath.stringAt('$.backupS3Uri') }], cdk.Duration.hours(3), tail);
|
|
85
|
+
entries['restore'] = restore;
|
|
86
|
+
tail = restore;
|
|
87
|
+
const reset = this.ecsStep('s0-fresh-reset', 'reset', [], cdk.Duration.minutes(30), restore);
|
|
88
|
+
entries['fresh-reset'] = reset;
|
|
89
|
+
const freshChoice = new sfn.Choice(this, 'FreshReset').when(sfn.Condition.booleanEquals('$.fresh', true), reset).otherwise(restore);
|
|
90
|
+
tail = freshChoice;
|
|
91
|
+
const fromStep = new sfn.Choice(this, 'FromStep');
|
|
92
|
+
for (const [stepId, entry] of Object.entries(entries)) {
|
|
93
|
+
fromStep.when(sfn.Condition.and(sfn.Condition.isPresent('$.fromStep'), sfn.Condition.stringEquals('$.fromStep', stepId)), entry);
|
|
94
|
+
}
|
|
95
|
+
fromStep.otherwise(freshChoice);
|
|
96
|
+
tail = fromStep;
|
|
97
|
+
const logGroup = new logs.LogGroup(this, 'Logs', {
|
|
98
|
+
logGroupName: '/aws/vendedlogs/states/migration-orchestrator',
|
|
99
|
+
retention: logs.RetentionDays.THREE_MONTHS,
|
|
100
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
101
|
+
});
|
|
102
|
+
this.stateMachine = new sfn.StateMachine(this, 'StateMachine', {
|
|
103
|
+
stateMachineName: 'migration-orchestrator',
|
|
104
|
+
definitionBody: sfn.DefinitionBody.fromChainable(tail),
|
|
105
|
+
timeout: cdk.Duration.days(7),
|
|
106
|
+
logs: {
|
|
107
|
+
destination: logGroup,
|
|
108
|
+
level: sfn.LogLevel.ALL,
|
|
109
|
+
includeExecutionData: true,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
this.producer.grantInvoke(this.stateMachine);
|
|
113
|
+
this.verifier.grantInvoke(this.stateMachine);
|
|
114
|
+
this.queue.grant(this.stateMachine, 'sqs:GetQueueAttributes');
|
|
115
|
+
this.taskDefinition.grantRun(this.stateMachine);
|
|
116
|
+
}
|
|
117
|
+
// Producer loop (until endReached, guarded by maxInvocations) -> queue drain
|
|
118
|
+
// (Visible + NotVisible = 0, guarded by drainMaxChecks) -> next.
|
|
119
|
+
producerPass(id, payload, next) {
|
|
120
|
+
const failure = new sfn.Fail(this, `${id}-Failed`, {
|
|
121
|
+
error: 'MigrationStepFailed',
|
|
122
|
+
cause: `Step ${id} exceeded its iteration/drain guard, or an ECS script task failed.`,
|
|
123
|
+
});
|
|
124
|
+
const init = new sfn.Pass(this, `${id}-LoopInit`, {
|
|
125
|
+
parameters: { count: 0 },
|
|
126
|
+
resultPath: '$.loop',
|
|
127
|
+
});
|
|
128
|
+
const invoke = new tasks.LambdaInvoke(this, `${id}-Invoke`, {
|
|
129
|
+
lambdaFunction: this.producer,
|
|
130
|
+
payload: sfn.TaskInput.fromObject(payload),
|
|
131
|
+
payloadResponseOnly: true,
|
|
132
|
+
resultPath: '$.producer',
|
|
133
|
+
taskTimeout: sfn.Timeout.duration(cdk.Duration.minutes(15)),
|
|
134
|
+
});
|
|
135
|
+
invoke.addRetry({
|
|
136
|
+
errors: ['States.TaskFailed', 'Lambda.ServiceException', 'Lambda.AWSLambdaException', 'Lambda.SdkClientException'],
|
|
137
|
+
maxAttempts: 2,
|
|
138
|
+
interval: cdk.Duration.seconds(30),
|
|
139
|
+
backoffRate: 2,
|
|
140
|
+
});
|
|
141
|
+
const endReached = new sfn.Choice(this, `${id}-EndReached`);
|
|
142
|
+
const loopInc = new sfn.Pass(this, `${id}-LoopInc`, {
|
|
143
|
+
parameters: { count: sfn.JsonPath.mathAdd(sfn.JsonPath.numberAt('$.loop.count'), 1) },
|
|
144
|
+
resultPath: '$.loop',
|
|
145
|
+
});
|
|
146
|
+
const loopGuard = new sfn.Choice(this, `${id}-LoopGuard`).when(sfn.Condition.numberGreaterThan('$.loop.count', this.maxInvocations), failure);
|
|
147
|
+
const loopWait = new sfn.Wait(this, `${id}-LoopWait`, {
|
|
148
|
+
time: sfn.WaitTime.duration(cdk.Duration.seconds(this.loopWaitSeconds)),
|
|
149
|
+
});
|
|
150
|
+
const drainInit = new sfn.Pass(this, `${id}-DrainInit`, {
|
|
151
|
+
parameters: { count: 0 },
|
|
152
|
+
resultPath: '$.drain',
|
|
153
|
+
});
|
|
154
|
+
const drainGet = new tasks.CallAwsService(this, `${id}-QueueAttributes`, {
|
|
155
|
+
service: 'sqs',
|
|
156
|
+
action: 'getQueueAttributes',
|
|
157
|
+
parameters: {
|
|
158
|
+
QueueUrl: this.queue.queueUrl,
|
|
159
|
+
AttributeNames: ['ApproximateNumberOfMessages', 'ApproximateNumberOfMessagesNotVisible'],
|
|
160
|
+
},
|
|
161
|
+
iamResources: [this.queue.queueArn],
|
|
162
|
+
resultPath: '$.queue',
|
|
163
|
+
});
|
|
164
|
+
const drained = new sfn.Choice(this, `${id}-Drained`).when(sfn.Condition.and(sfn.Condition.stringEquals('$.queue.Attributes.ApproximateNumberOfMessages', '0'), sfn.Condition.stringEquals('$.queue.Attributes.ApproximateNumberOfMessagesNotVisible', '0')), next);
|
|
165
|
+
const drainInc = new sfn.Pass(this, `${id}-DrainInc`, {
|
|
166
|
+
parameters: { count: sfn.JsonPath.mathAdd(sfn.JsonPath.numberAt('$.drain.count'), 1) },
|
|
167
|
+
resultPath: '$.drain',
|
|
168
|
+
});
|
|
169
|
+
const drainGuard = new sfn.Choice(this, `${id}-DrainGuard`).when(sfn.Condition.numberGreaterThan('$.drain.count', this.drainMaxChecks), failure);
|
|
170
|
+
const drainWait = new sfn.Wait(this, `${id}-DrainWait`, {
|
|
171
|
+
time: sfn.WaitTime.duration(cdk.Duration.seconds(this.drainWaitSeconds)),
|
|
172
|
+
});
|
|
173
|
+
init.next(invoke);
|
|
174
|
+
invoke.next(endReached);
|
|
175
|
+
endReached.when(sfn.Condition.booleanEquals('$.producer.endReached', true), drainInit).otherwise(loopInc);
|
|
176
|
+
loopInc.next(loopGuard);
|
|
177
|
+
loopGuard.otherwise(loopWait);
|
|
178
|
+
loopWait.next(invoke);
|
|
179
|
+
drainInit.next(drainGet);
|
|
180
|
+
drainGet.next(drained);
|
|
181
|
+
drained.otherwise(drainInc);
|
|
182
|
+
drainInc.next(drainGuard);
|
|
183
|
+
drainGuard.otherwise(drainWait);
|
|
184
|
+
drainWait.next(drainGet);
|
|
185
|
+
return init;
|
|
186
|
+
}
|
|
187
|
+
// Main pass, then a skipMigrated retry pass (fromStart) that re-publishes
|
|
188
|
+
// only records without a migrated row.
|
|
189
|
+
resourceStep(id, payload, next) {
|
|
190
|
+
const terminal = next ?? new sfn.Succeed(this, `${id}-Done`);
|
|
191
|
+
const retry = this.producerPass(`${id}-Retry`, { ...payload, fromStart: true, skipMigrated: true }, terminal);
|
|
192
|
+
return this.producerPass(id, payload, retry);
|
|
193
|
+
}
|
|
194
|
+
ecsStep(id, command, environment, timeout, next) {
|
|
195
|
+
const run = new tasks.EcsRunTask(this, id, {
|
|
196
|
+
integrationPattern: sfn.IntegrationPattern.RUN_JOB,
|
|
197
|
+
cluster: this.cluster,
|
|
198
|
+
taskDefinition: this.taskDefinition,
|
|
199
|
+
launchTarget: new tasks.EcsFargateLaunchTarget({ platformVersion: ecs.FargatePlatformVersion.LATEST }),
|
|
200
|
+
containerOverrides: [
|
|
201
|
+
{
|
|
202
|
+
containerDefinition: this.container,
|
|
203
|
+
command: [command],
|
|
204
|
+
environment,
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
208
|
+
securityGroups: [this.securityGroup],
|
|
209
|
+
assignPublicIp: false,
|
|
210
|
+
taskTimeout: sfn.Timeout.duration(timeout),
|
|
211
|
+
});
|
|
212
|
+
run.addRetry({
|
|
213
|
+
errors: ['States.TaskFailed'],
|
|
214
|
+
maxAttempts: 1,
|
|
215
|
+
interval: cdk.Duration.minutes(1),
|
|
216
|
+
backoffRate: 2,
|
|
217
|
+
});
|
|
218
|
+
run.next(next);
|
|
219
|
+
return run;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
exports.MigrationStateMachine = MigrationStateMachine;
|
|
223
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLXN0YXRlLW1hY2hpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9jb25zdHJ1Y3RzL21pZ3JhdGlvbi1zdGF0ZS1tYWNoaW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUFtQztBQUNuQywyQ0FBMkM7QUFDM0MsMkNBQTJDO0FBRTNDLDZDQUE2QztBQUc3QyxxREFBcUQ7QUFDckQsNkRBQTZEO0FBQzdELDJDQUF1QztBQW1CdkMsc0VBQXNFO0FBQ3RFLDZFQUE2RTtBQUM3RSw0REFBNEQ7QUFDNUQsTUFBYSxxQkFBc0IsU0FBUSxzQkFBUztJQWdCbEQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFpQztRQUN6RSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQztRQUMvQixJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7UUFDL0IsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztRQUM3QixJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUM7UUFDM0MsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQztRQUN6QyxJQUFJLENBQUMsZUFBZSxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUM7UUFDN0MsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQztRQUNuRCxJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLElBQUksR0FBRyxDQUFDO1FBQ2xELElBQUksQ0FBQyxlQUFlLEdBQUcsS0FBSyxD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QXNCLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdEcsa0JBQWtCLEVBQUU7Z0JBQ2xCO29CQUNFLG1CQUFtQixFQUFFLElBQUksQ0FBQyxTQUFTO29CQUNuQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUM7b0JBQ2xCLFdBQVc7aUJBQ1o7YUFDRjtZQUNELE9BQU8sRUFBRSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLG1CQUFtQixFQUFFO1lBQzNELGNBQWMsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7WUFDcEMsY0FBYyxFQUFFLEtBQUs7WUFDckIsV0FBVyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztTQUMzQyxDQUFDLENBQUM7UUFDSCxHQUFHLENBQUMsUUFBUSxDQUFDO1lBQ1gsTUFBTSxFQUFFLENBQUMsbUJBQW1CLENBQUM7WUFDN0IsV0FBVyxFQUFFLENBQUM7WUFDZCxRQUFRLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ2pDLFdBQVcsRUFBRSxDQUFDO1NBQ2YsQ0FBQyxDQUFDO1FBQ0gsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNmLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztDQUNGO0FBL1FELHNEQStRQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgKiBhcyBlY3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjcyc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgKiBhcyBsb2dzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sb2dzJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgKiBhcyBzcXMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNxcyc7XG5pbXBvcnQgKiBhcyBzZm4gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMnO1xuaW1wb3J0ICogYXMgdGFza3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMtdGFza3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWlncmF0aW9uU3RhdGVNYWNoaW5lUHJvcHMge1xuICBwcm9kdWNlcjogbGFtYmRhLklGdW5jdGlvbjtcbiAgdmVyaWZpZXI6IGxhbWJkYS5JRnVuY3Rpb247XG4gIHF1ZXVlOiBzcXMuSVF1ZXVlO1xuICBjbHVzdGVyOiBlY3MuSUNsdXN0ZXI7XG4gIHRhc2tEZWZpbml0aW9uOiBlY3MuVGFza0RlZmluaXRpb247XG4gIGNvbnRhaW5lcjogZWNzLkNvbnRhaW5lckRlZmluaXRpb247XG4gIHNlY3VyaXR5R3JvdXA6IGVjMi5JU2VjdXJpdHlHcm91cDtcbiAgYXJ0aWZhY3RzQnVja2V0OiBzMy5JQnVja2V0O1xuICBtYXhJbnZvY2F0aW9ucz86IG51bWJlcjtcbiAgZHJhaW5NYXhDaGVja3M/OiBudW1iZXI7XG4gIGxvb3BXYWl0U2Vjb25kcz86IG51bWJlcjtcbiAgZHJhaW5XYWl0U2Vjb25kcz86IG51bWJlcjtcbn1cblxudHlwZSBQcm9kdWNlclBheWxvYWQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuLy8gUnVucyB0aGUgcnVuYm9vayBlbmQtdG8tZW5kOiBzY3JpcHRzIGFzIG9uZS1zaG90IEZhcmdhdGUgdGFza3MsIFNRU1xuLy8gbWlncmF0YWJsZXMgYXMgcHJvZHVjZXIgbG9vcHMgKHVudGlsIGVuZFJlYWNoZWQpIGZvbGxvd2VkIGJ5IGEgcXVldWUgZHJhaW5cbi8vIGFuZCBhIHNraXBNaWdyYXRlZCByZXRyeSBwYXNzLCB0aGVuIHRoZSB2ZXJpZmllciBzdW1tYXJ5LlxuZXhwb3J0IGNsYXNzIE1pZ3JhdGlvblN0YXRlTWFjaGluZSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSBzdGF0ZU1hY2hpbmU6IHNmbi5TdGF0ZU1hY2hpbmU7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwcm9kdWNlcjogbGFtYmRhLklGdW5jdGlvbjtcbiAgcHJpdmF0ZSByZWFkb25seSB2ZXJpZmllcjogbGFtYmRhLklGdW5jdGlvbjtcbiAgcHJpdmF0ZSByZWFkb25seSBxdWV1ZTogc3FzLklRdWV1ZTtcbiAgcHJpdmF0ZSByZWFkb25seSBjbHVzdGVyOiBlY3MuSUNsdXN0ZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgdGFza0RlZmluaXRpb246IGVjcy5UYXNrRGVmaW5pdGlvbjtcbiAgcHJpdmF0ZSByZWFkb25seSBjb250YWluZXI6IGVjcy5Db250YWluZXJEZWZpbml0aW9uO1xuICBwcml2YXRlIHJlYWRvbmx5IHNlY3VyaXR5R3JvdXA6IGVjMi5JU2VjdXJpdHlHcm91cDtcbiAgcHJpdmF0ZSByZWFkb25seSBhcnRpZmFjdHNCdWNrZXQ6IHMzLklCdWNrZXQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWF4SW52b2NhdGlvbnM6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBkcmFpbk1heENoZWNrczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGxvb3BXYWl0U2Vjb25kczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGRyYWluV2FpdFNlY29uZHM6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogTWlncmF0aW9uU3RhdGVNYWNoaW5lUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgdGhpcy5wcm9kdWNlciA9IHByb3BzLnByb2R1Y2VyO1xuICAgIHRoaXMudmVyaWZpZXIgPSBwcm9wcy52ZXJpZmllcjtcbiAgICB0aGlzLnF1ZXVlID0gcHJvcHMucXVldWU7XG4gICAgdGhpcy5jbHVzdGVyID0gcHJvcHMuY2x1c3RlcjtcbiAgICB0aGlzLnRhc2tEZWZpbml0aW9uID0gcHJvcHMudGFza0RlZmluaXRpb247XG4gICAgdGhpcy5jb250YWluZXIgPSBwcm9wcy5jb250YWluZXI7XG4gICAgdGhpcy5zZWN1cml0eUdyb3VwID0gcHJvcHMuc2VjdXJpdHlHcm91cDtcbiAgICB0aGlzLmFydGlmYWN0c0J1Y2tldCA9IHByb3BzLmFydGlmYWN0c0J1Y2tldDtcbiAgICB0aGlzLm1heEludm9jYXRpb25zID0gcHJvcHMubWF4SW52b2NhdGlvbnMgPz8gMjAwMDtcbiAgICB0aGlzLmRyYWluTWF4Q2hlY2tzID0gcHJvcHMuZHJhaW5NYXhDaGVja3MgPz8gNjAwO1xuICAgIHRoaXMubG9vcFdhaXRTZWNvbmRzID0gcHJvcHMubG9vcFdhaXRTZWNvbmRzID8/IDEwO1xuICAgIHRoaXMuZHJhaW5XYWl0U2Vjb25kcyA9IHByb3BzLmRyYWluV2FpdFNlY29uZHMgPz8gMzAwO1xuXG4gICAgY29uc3QgZW50cmllczogUmVjb3JkPHN0cmluZywgc2ZuLklDaGFpbmFibGU+ID0ge307XG5cbiAgICBjb25zdCB2ZXJpZnkgPSBuZXcgdGFza3MuTGFtYmRhSW52b2tlKHRoaXMsICdWZXJpZnknLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy52ZXJpZmllcixcbiAgICAgIHBheWxvYWQ6IHNmbi5UYXNrSW5wdXQuZnJvbU9iamVjdCh7XG4gICAgICAgIHJ1bklkOiBzZm4uSnNvblBhdGguc3RyaW5nQXQoJyQkLkV4ZWN1dGlvbi5OYW1lJyksXG4gICAgICAgIGJ1Y2tldDogdGhpcy5hcnRpZmFjdHNCdWNrZXQuYnVja2V0TmFtZSxcbiAgICAgICAga2V5OiBzZm4uSnNvblBhdGguZm9ybWF0KCdydW5zL3t9L3N1bW1hcnkuanNvbicsIHNmbi5Kc29uUGF0aC5zdHJpbmdBdCgnJCQuRXhlY3V0aW9uLk5hbWUnKSksXG4gICAgICB9KSxcbiAgICAgIHBheWxvYWRSZXNwb25zZU9ubHk6IHRydWUsXG4gICAgICByZXN1bHRQYXRoOiAnJC52ZXJpZmljYXRpb24nLFxuICAgIH0pO1xuICAgIGNvbnN0IGNvbXBsZXRlID0gbmV3IHNmbi5TdWNjZWVkKHRoaXMsICdDb21wbGV0ZScpO1xuICAgIHZlcmlmeS5uZXh0KGNvbXBsZXRlKTtcblxuICAgIGxldCB0YWlsOiBzZm4uSUNoYWluYWJsZSA9IHZlcmlmeTtcblxuICAgIGVudHJpZXNbJ2NsYWltcyddID0gdGhpcy5yZXNvdXJjZVN0ZXAoJ3MxNi1jbGFpbXMnLCB7IHJlc291cmNlOiAnY2xhaW1zJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1snY2xhaW1zJ107XG5cbiAgICBjb25zdCBwaG90b3MgPSB0aGlzLnJlc291cmNlU3RlcCgnczE1LWJlbmVmaWNpYXJ5LXBob3RvcycsIHsgcmVzb3VyY2U6ICdiZW5lZmljaWFyeS1waG90b3MnIH0sIHRhaWwpO1xuICAgIGVudHJpZXNbJ2JlbmVmaWNpYXJ5LXBob3RvcyddID0gcGhvdG9zO1xuICAgIGNvbnN0IHBob3Rvc0Nob2ljZSA9IG5ldyBzZm4uQ2hvaWNlKHRoaXMsICdTa2lwUGhvdG9zJykud2hlbihzZm4uQ29uZGl0aW9uLmJvb2xlYW5FcXVhbHMoJyQuc2tpcFBob3RvcycsIHRydWUpLCB0YWlsKS5vdGhlcndpc2UocGhvdG9zKTtcbiAgICB0YWlsID0gcGhvdG9zQ2hvaWNlO1xuXG4gICAgZW50cmllc1snYmVuZWZpY2lhcmllcy1kZXBlbmRhbnRzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczE0Yi1iZW5lZmljaWFyaWVzLWRlcGVuZGFudHMnLCB7IHJlc291cmNlOiAnYmVuZWZpY2lhcmllcycsIHBoYXNlOiAnZGVwZW5kYW50cycgfSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ2JlbmVmaWNpYXJpZXMtZGVwZW5kYW50cyddO1xuXG4gICAgZW50cmllc1snYmVuZWZpY2lhcmllcy1wcmluY2lwYWxzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczE0YS1iZW5lZmljaWFyaWVzLXByaW5jaXBhbHMnLCB7IHJlc291cmNlOiAnYmVuZWZpY2lhcmllcycsIHBoYXNlOiAncHJpbmNpcGFscycgfSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ2JlbmVmaWNpYXJpZXMtcHJpbmNpcGFscyddO1xuXG4gICAgZW50cmllc1sncGxhbnMtcmV3aXJlJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczEzYi1wbGFucy1yZXdpcmUnLCB7IHJlc291cmNlOiAncGxhbnMnIH0sIHRhaWwpO1xuICAgIHRhaWwgPSBlbnRyaWVzWydwbGFucy1yZXdpcmUnXTtcblxuICAgIGVudHJpZXNbJ2JlbmVmaXRzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczEyLWJlbmVmaXRzJywgeyByZXNvdXJjZTogJ2JlbmVmaXRzJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1snYmVuZWZpdHMnXTtcblxuICAgIGVudHJpZXNbJ3BvbGljaWVzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczExLXBvbGljaWVzJywgeyByZXNvdXJjZTogJ3BvbGljaWVzJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1sncG9saWNpZXMnXTtcblxuICAgIGVudHJpZXNbJ3Byb2R1Y3QtcHJpY2luZyddID0gdGhpcy5yZXNvdXJjZVN0ZXAoJ3MxMC1wcm9kdWN0LXByaWNpbmcnLCB7IHJlc291cmNlOiAncHJvZHVjdC1wcmljaW5nJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1sncHJvZHVjdC1wcmljaW5nJ107XG5cbiAgICBjb25zdCB0aWVyMCA9IG5ldyBzZm4uUGFyYWxsZWwodGhpcywgJ3M5LXRpZXIwJywgeyByZXN1bHRQYXRoOiAnJC50aWVyMCcgfSk7XG4gICAgZm9yIChjb25zdCByZXNvdXJjZSBvZiBbJ3VzZXJzJywgJ3Byb3ZpZGVycycsICdpbnN1cmVkJywgJ3RwYScsICdwbGFucyddKSB7XG4gICAgICB0aWVyMC5icmFuY2goc2ZuLkNoYWluLnN0YXJ0KHRoaXMucmVzb3VyY2VTdGVwKGBzOS0ke3Jlc291cmNlfWAsIHsgcmVzb3VyY2UgfSkpKTtcbiAgICB9XG4gICAgdGllcjAubmV4dCh0YWlsKTtcbiAgICBlbnRyaWVzWyd0aWVyMCddID0gdGllcjA7XG4gICAgdGFpbCA9IHRpZXIwO1xuXG4gICAgZW50cmllc1snY292ZXJhZ2UtZ3JvdXBzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczgtY292ZXJhZ2UtZ3JvdXBzJywgeyByZXNvdXJjZTogJ2NvdmVyYWdlLWdyb3VwcycgfSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ2NvdmVyYWdlLWdyb3VwcyddO1xuXG4gICAgZW50cmllc1snY2F0ZWdvcmllcyddID0gdGhpcy5yZXNvdXJjZVN0ZXAoJ3M3LWNhdGVnb3JpZXMnLCB7IHJlc291cmNlOiAnY2F0ZWdvcmllcycgfSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ2NhdGVnb3JpZXMnXTtcblxuICAgIGVudHJpZXNbJ3Byb2R1Y3RzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczYtcHJvZHVjdHMnLCB7IHJlc291cmNlOiAncHJvZHVjdHMnIH0sIHRhaWwpO1xuICAgIHRhaWwgPSBlbnRyaWVzWydwcm9kdWN0cyddO1xuXG4gICAgZW50cmllc1sncHJvZHVjdC1jYXRlZ29yaWVzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczViLXByb2R1Y3QtY2F0ZWdvcmllcycsIHsgcmVzb3VyY2U6ICdwcm9kdWN0LWNhdGVnb3JpZXMnIH0sIHRhaWwpO1xuICAgIHRhaWwgPSBlbnRyaWVzWydwcm9kdWN0LWNhdGVnb3JpZXMnXTtcblxuICAgIGVudHJpZXNbJ3Byb2R1Y3Qtc291cmNlcyddID0gdGhpcy5yZXNvdXJjZVN0ZXAoJ3M1YS1wcm9kdWN0LXNvdXJjZXMnLCB7IHJlc291cmNlOiAncHJvZHVjdC1zb3VyY2VzJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1sncHJvZHVjdC1zb3VyY2VzJ107XG5cbiAgICBlbnRyaWVzWydjbGFpbS1iYXRjaGVzJ10gPSB0aGlzLmVjc1N0ZXAoJ3M0LWNsYWltLWJhdGNoZXMnLCAnY2xhaW0tYmF0Y2hlcycsIFtdLCBjZGsuRHVyYXRpb24uaG91cnMoMiksIHRhaWwpO1xuICAgIHRhaWwgPSBlbnRyaWVzWydjbGFpbS1iYXRjaGVzJ107XG5cbiAgICBlbnRyaWVzWydkaXNlYXNlcyddID0gdGhpcy5lY3NTdGVwKCdzMy1kaXNlYXNlLWxvb2t1cHMnLCAnZGlzZWFzZXMnLCBbXSwgY2RrLkR1cmF0aW9uLmhvdXJzKDEpLCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1snZGlzZWFzZXMnXTtcblxuICAgIGVudHJpZXNbJ21pZ3JhdGlvbnMnXSA9IHRoaXMuZWNzU3RlcCgnczItbWlncmF0aW9ucycsICdtaWdyYXRpb25zJywgW10sIGNkay5EdXJhdGlvbi5ob3VycygxKSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ21pZ3JhdGlvbnMnXTtcblxuICAgIGNvbnN0IHJlc3RvcmUgPSB0aGlzLmVjc1N0ZXAoXG4gICAgICAnczEtcmVzdG9yZScsXG4gICAgICAncmVzdG9yZScsXG4gICAgICBbeyBuYW1lOiAnQkFDS1VQX1MzX1VSSScsIHZhbHVlOiBzZm4uSnNvblBhdGguc3RyaW5nQXQoJyQuYmFja3VwUzNVcmknKSB9XSxcbiAgICAgIGNkay5EdXJhdGlvbi5ob3VycygzKSxcbiAgICAgIHRhaWxcbiAgICApO1xuICAgIGVudHJpZXNbJ3Jlc3RvcmUnXSA9IHJlc3RvcmU7XG4gICAgdGFpbCA9IHJlc3RvcmU7XG5cbiAgICBjb25zdCByZXNldCA9IHRoaXMuZWNzU3RlcCgnczAtZnJlc2gtcmVzZXQnLCAncmVzZXQnLCBbXSwgY2RrLkR1cmF0aW9uLm1pbnV0ZXMoMzApLCByZXN0b3JlKTtcbiAgICBlbnRyaWVzWydmcmVzaC1yZXNldCddID0gcmVzZXQ7XG4gICAgY29uc3QgZnJlc2hDaG9pY2UgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCAnRnJlc2hSZXNldCcpLndoZW4oc2ZuLkNvbmRpdGlvbi5ib29sZWFuRXF1YWxzKCckLmZyZXNoJywgdHJ1ZSksIHJlc2V0KS5vdGhlcndpc2UocmVzdG9yZSk7XG4gICAgdGFpbCA9IGZyZXNoQ2hvaWNlO1xuXG4gICAgY29uc3QgZnJvbVN0ZXAgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCAnRnJvbVN0ZXAnKTtcbiAgICBmb3IgKGNvbnN0IFtzdGVwSWQsIGVudHJ5XSBvZiBPYmplY3QuZW50cmllcyhlbnRyaWVzKSkge1xuICAgICAgZnJvbVN0ZXAud2hlbihzZm4uQ29uZGl0aW9uLmFuZChzZm4uQ29uZGl0aW9uLmlzUHJlc2VudCgnJC5mcm9tU3RlcCcpLCBzZm4uQ29uZGl0aW9uLnN0cmluZ0VxdWFscygnJC5mcm9tU3RlcCcsIHN0ZXBJZCkpLCBlbnRyeSk7XG4gICAgfVxuICAgIGZyb21TdGVwLm90aGVyd2lzZShmcmVzaENob2ljZSk7XG4gICAgdGFpbCA9IGZyb21TdGVwO1xuXG4gICAgY29uc3QgbG9nR3JvdXAgPSBuZXcgbG9ncy5Mb2dHcm91cCh0aGlzLCAnTG9ncycsIHtcbiAgICAgIGxvZ0dyb3VwTmFtZTogJy9hd3MvdmVuZGVkbG9ncy9zdGF0ZXMvbWlncmF0aW9uLW9yY2hlc3RyYXRvcicsXG4gICAgICByZXRlbnRpb246IGxvZ3MuUmV0ZW50aW9uRGF5cy5USFJFRV9NT05USFMsXG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zdGF0ZU1hY2hpbmUgPSBuZXcgc2ZuLlN0YXRlTWFjaGluZSh0aGlzLCAnU3RhdGVNYWNoaW5lJywge1xuICAgICAgc3RhdGVNYWNoaW5lTmFtZTogJ21pZ3JhdGlvbi1vcmNoZXN0cmF0b3InLFxuICAgICAgZGVmaW5pdGlvbkJvZHk6IHNmbi5EZWZpbml0aW9uQm9keS5mcm9tQ2hhaW5hYmxlKHRhaWwpLFxuICAgICAgdGltZW91dDogY2RrLkR1cmF0aW9uLmRheXMoNyksXG4gICAgICBsb2dzOiB7XG4gICAgICAgIGRlc3RpbmF0aW9uOiBsb2dHcm91cCxcbiAgICAgICAgbGV2ZWw6IHNmbi5Mb2dMZXZlbC5BTEwsXG4gICAgICAgIGluY2x1ZGVFeGVjdXRpb25EYXRhOiB0cnVlLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHRoaXMucHJvZHVjZXIuZ3JhbnRJbnZva2UodGhpcy5zdGF0ZU1hY2hpbmUpO1xuICAgIHRoaXMudmVyaWZpZXIuZ3JhbnRJbnZva2UodGhpcy5zdGF0ZU1hY2hpbmUpO1xuICAgIHRoaXMucXVldWUuZ3JhbnQodGhpcy5zdGF0ZU1hY2hpbmUsICdzcXM6R2V0UXVldWVBdHRyaWJ1dGVzJyk7XG4gICAgdGhpcy50YXNrRGVmaW5pdGlvbi5ncmFudFJ1bih0aGlzLnN0YXRlTWFjaGluZSk7XG4gIH1cblxuICAvLyBQcm9kdWNlciBsb29wICh1bnRpbCBlbmRSZWFjaGVkLCBndWFyZGVkIGJ5IG1heEludm9jYXRpb25zKSAtPiBxdWV1ZSBkcmFpblxuICAvLyAoVmlzaWJsZSArIE5vdFZpc2libGUgPSAwLCBndWFyZGVkIGJ5IGRyYWluTWF4Q2hlY2tzKSAtPiBuZXh0LlxuICBwcml2YXRlIHByb2R1Y2VyUGFzcyhpZDogc3RyaW5nLCBwYXlsb2FkOiBQcm9kdWNlclBheWxvYWQsIG5leHQ6IHNmbi5JQ2hhaW5hYmxlKTogc2ZuLklDaGFpbmFibGUge1xuICAgIGNvbnN0IGZhaWx1cmUgPSBuZXcgc2ZuLkZhaWwodGhpcywgYCR7aWR9LUZhaWxlZGAsIHtcbiAgICAgIGVycm9yOiAnTWlncmF0aW9uU3RlcEZhaWxlZCcsXG4gICAgICBjYXVzZTogYFN0ZXAgJHtpZH0gZXhjZWVkZWQgaXRzIGl0ZXJhdGlvbi9kcmFpbiBndWFyZCwgb3IgYW4gRUNTIHNjcmlwdCB0YXNrIGZhaWxlZC5gLFxuICAgIH0pO1xuXG4gICAgY29uc3QgaW5pdCA9IG5ldyBzZm4uUGFzcyh0aGlzLCBgJHtpZH0tTG9vcEluaXRgLCB7XG4gICAgICBwYXJhbWV0ZXJzOiB7IGNvdW50OiAwIH0sXG4gICAgICByZXN1bHRQYXRoOiAnJC5sb29wJyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGludm9rZSA9IG5ldyB0YXNrcy5MYW1iZGFJbnZva2UodGhpcywgYCR7aWR9LUludm9rZWAsIHtcbiAgICAgIGxhbWJkYUZ1bmN0aW9uOiB0aGlzLnByb2R1Y2VyLFxuICAgICAgcGF5bG9hZDogc2ZuLlRhc2tJbnB1dC5mcm9tT2JqZWN0KHBheWxvYWQpLFxuICAgICAgcGF5bG9hZFJlc3BvbnNlT25seTogdHJ1ZSxcbiAgICAgIHJlc3VsdFBhdGg6ICckLnByb2R1Y2VyJyxcbiAgICAgIHRhc2tUaW1lb3V0OiBzZm4uVGltZW91dC5kdXJhdGlvbihjZGsuRHVyYXRpb24ubWludXRlcygxNSkpLFxuICAgIH0pO1xuICAgIGludm9rZS5hZGRSZXRyeSh7XG4gICAgICBlcnJvcnM6IFsnU3RhdGVzLlRhc2tGYWlsZWQnLCAnTGFtYmRhLlNlcnZpY2VFeGNlcHRpb24nLCAnTGFtYmRhLkFXU0xhbWJkYUV4Y2VwdGlvbicsICdMYW1iZGEuU2RrQ2xpZW50RXhjZXB0aW9uJ10sXG4gICAgICBtYXhBdHRlbXB0czogMixcbiAgICAgIGludGVydmFsOiBjZGsuRHVyYXRpb24uc2Vjb25kcygzMCksXG4gICAgICBiYWNrb2ZmUmF0ZTogMixcbiAgICB9KTtcblxuICAgIGNvbnN0IGVuZFJlYWNoZWQgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCBgJHtpZH0tRW5kUmVhY2hlZGApO1xuXG4gICAgY29uc3QgbG9vcEluYyA9IG5ldyBzZm4uUGFzcyh0aGlzLCBgJHtpZH0tTG9vcEluY2AsIHtcbiAgICAgIHBhcmFtZXRlcnM6IHsgY291bnQ6IHNmbi5Kc29uUGF0aC5tYXRoQWRkKHNmbi5Kc29uUGF0aC5udW1iZXJBdCgnJC5sb29wLmNvdW50JyksIDEpIH0sXG4gICAgICByZXN1bHRQYXRoOiAnJC5sb29wJyxcbiAgICB9KTtcbiAgICBjb25zdCBsb29wR3VhcmQgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCBgJHtpZH0tTG9vcEd1YXJkYCkud2hlbihzZm4uQ29uZGl0aW9uLm51bWJlckdyZWF0ZXJUaGFuKCckLmxvb3AuY291bnQnLCB0aGlzLm1heEludm9jYXRpb25zKSwgZmFpbHVyZSk7XG4gICAgY29uc3QgbG9vcFdhaXQgPSBuZXcgc2ZuLldhaXQodGhpcywgYCR7aWR9LUxvb3BXYWl0YCwge1xuICAgICAgdGltZTogc2ZuLldhaXRUaW1lLmR1cmF0aW9uKGNkay5EdXJhdGlvbi5zZWNvbmRzKHRoaXMubG9vcFdhaXRTZWNvbmRzKSksXG4gICAgfSk7XG5cbiAgICBjb25zdCBkcmFpbkluaXQgPSBuZXcgc2ZuLlBhc3ModGhpcywgYCR7aWR9LURyYWluSW5pdGAsIHtcbiAgICAgIHBhcmFtZXRlcnM6IHsgY291bnQ6IDAgfSxcbiAgICAgIHJlc3VsdFBhdGg6ICckLmRyYWluJyxcbiAgICB9KTtcbiAgICBjb25zdCBkcmFpbkdldCA9IG5ldyB0YXNrcy5DYWxsQXdzU2VydmljZSh0aGlzLCBgJHtpZH0tUXVldWVBdHRyaWJ1dGVzYCwge1xuICAgICAgc2VydmljZTogJ3NxcycsXG4gICAgICBhY3Rpb246ICdnZXRRdWV1ZUF0dHJpYnV0ZXMnLFxuICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICBRdWV1ZVVybDogdGhpcy5xdWV1ZS5xdWV1ZVVybCxcbiAgICAgICAgQXR0cmlidXRlTmFtZXM6IFsnQXBwcm94aW1hdGVOdW1iZXJPZk1lc3NhZ2VzJywgJ0FwcHJveGltYXRlTnVtYmVyT2ZNZXNzYWdlc05vdFZpc2libGUnXSxcbiAgICAgIH0sXG4gICAgICBpYW1SZXNvdXJjZXM6IFt0aGlzLnF1ZXVlLnF1ZXVlQXJuXSxcbiAgICAgIHJlc3VsdFBhdGg6ICckLnF1ZXVlJyxcbiAgICB9KTtcbiAgICBjb25zdCBkcmFpbmVkID0gbmV3IHNmbi5DaG9pY2UodGhpcywgYCR7aWR9LURyYWluZWRgKS53aGVuKFxuICAgICAgc2ZuLkNvbmRpdGlvbi5hbmQoXG4gICAgICAgIHNmbi5Db25kaXRpb24uc3RyaW5nRXF1YWxzKCckLnF1ZXVlLkF0dHJpYnV0ZXMuQXBwcm94aW1hdGVOdW1iZXJPZk1lc3NhZ2VzJywgJzAnKSxcbiAgICAgICAgc2ZuLkNvbmRpdGlvbi5zdHJpbmdFcXVhbHMoJyQucXVldWUuQXR0cmlidXRlcy5BcHByb3hpbWF0ZU51bWJlck9mTWVzc2FnZXNOb3RWaXNpYmxlJywgJzAnKVxuICAgICAgKSxcbiAgICAgIG5leHRcbiAgICApO1xuICAgIGNvbnN0IGRyYWluSW5jID0gbmV3IHNmbi5QYXNzKHRoaXMsIGAke2lkfS1EcmFpbkluY2AsIHtcbiAgICAgIHBhcmFtZXRlcnM6IHsgY291bnQ6IHNmbi5Kc29uUGF0aC5tYXRoQWRkKHNmbi5Kc29uUGF0aC5udW1iZXJBdCgnJC5kcmFpbi5jb3VudCcpLCAxKSB9LFxuICAgICAgcmVzdWx0UGF0aDogJyQuZHJhaW4nLFxuICAgIH0pO1xuICAgIGNvbnN0IGRyYWluR3VhcmQgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCBgJHtpZH0tRHJhaW5HdWFyZGApLndoZW4oc2ZuLkNvbmRpdGlvbi5udW1iZXJHcmVhdGVyVGhhbignJC5kcmFpbi5jb3VudCcsIHRoaXMuZHJhaW5NYXhDaGVja3MpLCBmYWlsdXJlKTtcbiAgICBjb25zdCBkcmFpbldhaXQgPSBuZXcgc2ZuLldhaXQodGhpcywgYCR7aWR9LURyYWluV2FpdGAsIHtcbiAgICAgIHRpbWU6IHNmbi5XYWl0VGltZS5kdXJhdGlvbihjZGsuRHVyYXRpb24uc2Vjb25kcyh0aGlzLmRyYWluV2FpdFNlY29uZHMpKSxcbiAgICB9KTtcblxuICAgIGluaXQubmV4dChpbnZva2UpO1xuICAgIGludm9rZS5uZXh0KGVuZFJlYWNoZWQpO1xuICAgIGVuZFJlYWNoZWQud2hlbihzZm4uQ29uZGl0aW9uLmJvb2xlYW5FcXVhbHMoJyQucHJvZHVjZXIuZW5kUmVhY2hlZCcsIHRydWUpLCBkcmFpbkluaXQpLm90aGVyd2lzZShsb29wSW5jKTtcbiAgICBsb29wSW5jLm5leHQobG9vcEd1YXJkKTtcbiAgICBsb29wR3VhcmQub3RoZXJ3aXNlKGxvb3BXYWl0KTtcbiAgICBsb29wV2FpdC5uZXh0KGludm9rZSk7XG4gICAgZHJhaW5Jbml0Lm5leHQoZHJhaW5HZXQpO1xuICAgIGRyYWluR2V0Lm5leHQoZHJhaW5lZCk7XG4gICAgZHJhaW5lZC5vdGhlcndpc2UoZHJhaW5JbmMpO1xuICAgIGRyYWluSW5jLm5leHQoZHJhaW5HdWFyZCk7XG4gICAgZHJhaW5HdWFyZC5vdGhlcndpc2UoZHJhaW5XYWl0KTtcbiAgICBkcmFpbldhaXQubmV4dChkcmFpbkdldCk7XG5cbiAgICByZXR1cm4gaW5pdDtcbiAgfVxuXG4gIC8vIE1haW4gcGFzcywgdGhlbiBhIHNraXBNaWdyYXRlZCByZXRyeSBwYXNzIChmcm9tU3RhcnQpIHRoYXQgcmUtcHVibGlzaGVzXG4gIC8vIG9ubHkgcmVjb3JkcyB3aXRob3V0IGEgbWlncmF0ZWQgcm93LlxuICBwcml2YXRlIHJlc291cmNlU3RlcChpZDogc3RyaW5nLCBwYXlsb2FkOiBQcm9kdWNlclBheWxvYWQsIG5leHQ/OiBzZm4uSUNoYWluYWJsZSk6IHNmbi5JQ2hhaW5hYmxlIHtcbiAgICBjb25zdCB0ZXJtaW5hbCA9IG5leHQgPz8gbmV3IHNmbi5TdWNjZWVkKHRoaXMsIGAke2lkfS1Eb25lYCk7XG4gICAgY29uc3QgcmV0cnkgPSB0aGlzLnByb2R1Y2VyUGFzcyhgJHtpZH0tUmV0cnlgLCB7IC4uLnBheWxvYWQsIGZyb21TdGFydDogdHJ1ZSwgc2tpcE1pZ3JhdGVkOiB0cnVlIH0sIHRlcm1pbmFsKTtcbiAgICByZXR1cm4gdGhpcy5wcm9kdWNlclBhc3MoaWQsIHBheWxvYWQsIHJldHJ5KTtcbiAgfVxuXG4gIHByaXZhdGUgZWNzU3RlcChpZDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcsIGVudmlyb25tZW50OiB7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB9W10sIHRpbWVvdXQ6IGNkay5EdXJhdGlvbiwgbmV4dDogc2ZuLklDaGFpbmFibGUpOiBzZm4uSUNoYWluYWJsZSB7XG4gICAgY29uc3QgcnVuID0gbmV3IHRhc2tzLkVjc1J1blRhc2sodGhpcywgaWQsIHtcbiAgICAgIGludGVncmF0aW9uUGF0dGVybjogc2ZuLkludGVncmF0aW9uUGF0dGVybi5SVU5fSk9CLFxuICAgICAgY2x1c3RlcjogdGhpcy5jbHVzdGVyLFxuICAgICAgdGFza0RlZmluaXRpb246IHRoaXMudGFza0RlZmluaXRpb24sXG4gICAgICBsYXVuY2hUYXJnZXQ6IG5ldyB0YXNrcy5FY3NGYXJnYXRlTGF1bmNoVGFyZ2V0KHsgcGxhdGZvcm1WZXJzaW9uOiBlY3MuRmFyZ2F0ZVBsYXRmb3JtVmVyc2lvbi5MQVRFU1QgfSksXG4gICAgICBjb250YWluZXJPdmVycmlkZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGNvbnRhaW5lckRlZmluaXRpb246IHRoaXMuY29udGFpbmVyLFxuICAgICAgICAgIGNvbW1hbmQ6IFtjb21tYW5kXSxcbiAgICAgICAgICBlbnZpcm9ubWVudCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBzdWJuZXRzOiB7IHN1Ym5ldFR5cGU6IGVjMi5TdWJuZXRUeXBlLlBSSVZBVEVfV0lUSF9FR1JFU1MgfSxcbiAgICAgIHNlY3VyaXR5R3JvdXBzOiBbdGhpcy5zZWN1cml0eUdyb3VwXSxcbiAgICAgIGFzc2lnblB1YmxpY0lwOiBmYWxzZSxcbiAgICAgIHRhc2tUaW1lb3V0OiBzZm4uVGltZW91dC5kdXJhdGlvbih0aW1lb3V0KSxcbiAgICB9KTtcbiAgICBydW4uYWRkUmV0cnkoe1xuICAgICAgZXJyb3JzOiBbJ1N0YXRlcy5UYXNrRmFpbGVkJ10sXG4gICAgICBtYXhBdHRlbXB0czogMSxcbiAgICAgIGludGVydmFsOiBjZGsuRHVyYXRpb24ubWludXRlcygxKSxcbiAgICAgIGJhY2tvZmZSYXRlOiAyLFxuICAgIH0pO1xuICAgIHJ1bi5uZXh0KG5leHQpO1xuICAgIHJldHVybiBydW47XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MicroserviceClickHouse = void 0;
|
|
4
|
+
const cdk = require("aws-cdk-lib");
|
|
5
|
+
const constants_1 = require("../util/constants");
|
|
6
|
+
const initBuildConfig_1 = require("../util/initBuildConfig");
|
|
7
|
+
const getInstanceType_1 = require("../util/getInstanceType");
|
|
8
|
+
const getEc2UserData_1 = require("../util/getEc2UserData");
|
|
9
|
+
const getInstanceStorage_1 = require("../util/getInstanceStorage");
|
|
10
|
+
class MicroserviceClickHouse extends cdk.Stack {
|
|
11
|
+
constructor(scope, id, props) {
|
|
12
|
+
super(scope, id, props);
|
|
13
|
+
if (!initBuildConfig_1.buildConfig) {
|
|
14
|
+
throw new Error('BuildConfig not set');
|
|
15
|
+
}
|
|
16
|
+
const vpc = cdk.aws_ec2.Vpc.fromLookup(this, 'VPCLookup', {
|
|
17
|
+
vpcName: (0, constants_1.getEnvConstant)('vpcId'),
|
|
18
|
+
});
|
|
19
|
+
const secGroup = cdk.aws_ec2.SecurityGroup.fromLookupByName(this, 'SecGroupLookup', (0, constants_1.getEnvConstant)('clickhouseSecurityGroupId'), vpc);
|
|
20
|
+
const instance = new cdk.aws_ec2.Instance(this, `ec2-clickhouse-${initBuildConfig_1.buildConfig.envName}`, {
|
|
21
|
+
vpc,
|
|
22
|
+
securityGroup: secGroup,
|
|
23
|
+
instanceType: new cdk.aws_ec2.InstanceType((0, getInstanceType_1.getInstanceType)('clickhouse')),
|
|
24
|
+
machineImage: cdk.aws_ec2.MachineImage.genericLinux({
|
|
25
|
+
[initBuildConfig_1.buildConfig.aws.region]: (0, constants_1.getConstant)('defaultImageAmi'),
|
|
26
|
+
}),
|
|
27
|
+
vpcSubnets: { subnetType: cdk.aws_ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
28
|
+
associatePublicIpAddress: false,
|
|
29
|
+
userData: cdk.aws_ec2.UserData.custom((0, getEc2UserData_1.getEc2UserData)('clickhouse')),
|
|
30
|
+
role: cdk.aws_iam.Role.fromRoleName(this, 'BaseRoleLookup', (0, constants_1.getConstant)('baseRoleName')),
|
|
31
|
+
blockDevices: (0, getInstanceStorage_1.getInstanceStorage)('clickhouse'),
|
|
32
|
+
});
|
|
33
|
+
new cdk.CfnOutput(this, 'internal-domain', {
|
|
34
|
+
value: instance.instancePrivateDnsName,
|
|
35
|
+
});
|
|
36
|
+
new cdk.CfnOutput(this, 'internal-ip', {
|
|
37
|
+
value: instance.instancePrivateIp,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.MicroserviceClickHouse = MicroserviceClickHouse;
|
|
42
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWljcm9zZXJ2aWNlLWNsaWNraG91c2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvbWljcm9zZXJ2aWNlLWNsaWNraG91c2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQW1DO0FBRW5DLGlEQUFnRTtBQUNoRSw2REFBc0Q7QUFDdEQsNkRBQTBEO0FBQzFELDJEQUF3RDtBQUN4RCxtRUFBZ0U7QUFFaEUsTUFBYSxzQkFBdUIsU0FBUSxHQUFHLENBQUMsS0FBSztJQUNuRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXNCO1FBQzlELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXhCLElBQUksQ0FBQyw2QkFBVyxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3pDLENBQUM7UUFFRCxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRTtZQUN4RCxPQUFPLEVBQUUsSUFBQSwwQkFBYyxFQUFDLE9BQU8sQ0FBQztTQUNqQyxDQUFDLENBQUM7UUFFSCxNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsSUFBQSwwQkFBYyxFQUFDLDJCQUEyQixDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFdEksTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLDZCQUFXLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDdkYsR0FBRztZQUNILGFBQWEsRUFBRSxRQUFRO1lBQ3ZCLFlBQVksRUFBRSxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUEsaUNBQWUsRUFBQyxZQUFZLENBQUMsQ0FBQztZQUN6RSxZQUFZLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDO2dCQUNsRCxDQUFDLDZCQUFXLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUEsdUJBQVcsRUFBQyxpQkFBaUIsQ0FBVzthQUNuRSxDQUFDO1lBQ0YsVUFBVSxFQUFFLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLG1CQUFtQixFQUFFO1lBQ3RFLHdCQUF3QixFQUFFLEtBQUs7WUFDL0IsUUFBUSxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFBLCtCQUFjLEVBQUMsWUFBWSxDQUFDLENBQUM7WUFDbkUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsSUFBQSx1QkFBVyxFQUFDLGNBQWMsQ0FBVyxDQUFDO1lBQ2xHLFlBQVksRUFBRSxJQUFBLHVDQUFrQixFQUFDLFlBQVksQ0FBQztTQUMvQyxDQUFDLENBQUM7UUFFSCxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ3pDLEtBQUssRUFBRSxRQUFRLENBQUMsc0JBQXNCO1NBQ3ZDLENBQUMsQ0FBQztRQUVILElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFO1lBQ3JDLEtBQUssRUFBRSxRQUFRLENBQUMsaUJBQWlCO1NBQ2xDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQXBDRCx3REFvQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBnZXRDb25zdGFudCwgZ2V0RW52Q29uc3RhbnQgfSBmcm9tICcuLi91dGlsL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBidWlsZENvbmZpZyB9IGZyb20gJy4uL3V0aWwvaW5pdEJ1aWxkQ29uZmlnJztcbmltcG9ydCB7IGdldEluc3RhbmNlVHlwZSB9IGZyb20gJy4uL3V0aWwvZ2V0SW5zdGFuY2VUeXBlJztcbmltcG9ydCB7IGdldEVjMlVzZXJEYXRhIH0gZnJvbSAnLi4vdXRpbC9nZXRFYzJVc2VyRGF0YSc7XG5pbXBvcnQgeyBnZXRJbnN0YW5jZVN0b3JhZ2UgfSBmcm9tICcuLi91dGlsL2dldEluc3RhbmNlU3RvcmFnZSc7XG5cbmV4cG9ydCBjbGFzcyBNaWNyb3NlcnZpY2VDbGlja0hvdXNlIGV4dGVuZHMgY2RrLlN0YWNrIHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM/OiBjZGsuU3RhY2tQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwgcHJvcHMpO1xuXG4gICAgaWYgKCFidWlsZENvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCdWlsZENvbmZpZyBub3Qgc2V0Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgdnBjID0gY2RrLmF3c19lYzIuVnBjLmZyb21Mb29rdXAodGhpcywgJ1ZQQ0xvb2t1cCcsIHtcbiAgICAgIHZwY05hbWU6IGdldEVudkNvbnN0YW50KCd2cGNJZCcpLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc2VjR3JvdXAgPSBjZGsuYXdzX2VjMi5TZWN1cml0eUdyb3VwLmZyb21Mb29rdXBCeU5hbWUodGhpcywgJ1NlY0dyb3VwTG9va3VwJywgZ2V0RW52Q29uc3RhbnQoJ2NsaWNraG91c2VTZWN1cml0eUdyb3VwSWQnKSwgdnBjKTtcblxuICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IGNkay5hd3NfZWMyLkluc3RhbmNlKHRoaXMsIGBlYzItY2xpY2tob3VzZS0ke2J1aWxkQ29uZmlnLmVudk5hbWV9YCwge1xuICAgICAgdnBjLFxuICAgICAgc2VjdXJpdHlHcm91cDogc2VjR3JvdXAsXG4gICAgICBpbnN0YW5jZVR5cGU6IG5ldyBjZGsuYXdzX2VjMi5JbnN0YW5jZVR5cGUoZ2V0SW5zdGFuY2VUeXBlKCdjbGlja2hvdXNlJykpLFxuICAgICAgbWFjaGluZUltYWdlOiBjZGsuYXdzX2VjMi5NYWNoaW5lSW1hZ2UuZ2VuZXJpY0xpbnV4KHtcbiAgICAgICAgW2J1aWxkQ29uZmlnLmF3cy5yZWdpb25dOiBnZXRDb25zdGFudCgnZGVmYXVsdEltYWdlQW1pJykgYXMgc3RyaW5nLFxuICAgICAgfSksXG4gICAgICB2cGNTdWJuZXRzOiB7IHN1Ym5ldFR5cGU6IGNkay5hd3NfZWMyLlN1Ym5ldFR5cGUuUFJJVkFURV9XSVRIX0VHUkVTUyB9LFxuICAgICAgYXNzb2NpYXRlUHVibGljSXBBZGRyZXNzOiBmYWxzZSxcbiAgICAgIHVzZXJEYXRhOiBjZGsuYXdzX2VjMi5Vc2VyRGF0YS5jdXN0b20oZ2V0RWMyVXNlckRhdGEoJ2NsaWNraG91c2UnKSksXG4gICAgICByb2xlOiBjZGsuYXdzX2lhbS5Sb2xlLmZyb21Sb2xlTmFtZSh0aGlzLCAnQmFzZVJvbGVMb29rdXAnLCBnZXRDb25zdGFudCgnYmFzZVJvbGVOYW1lJykgYXMgc3RyaW5nKSxcbiAgICAgIGJsb2NrRGV2aWNlczogZ2V0SW5zdGFuY2VTdG9yYWdlKCdjbGlja2hvdXNlJyksXG4gICAgfSk7XG5cbiAgICBuZXcgY2RrLkNmbk91dHB1dCh0aGlzLCAnaW50ZXJuYWwtZG9tYWluJywge1xuICAgICAgdmFsdWU6IGluc3RhbmNlLmluc3RhbmNlUHJpdmF0ZURuc05hbWUsXG4gICAgfSk7XG5cbiAgICBuZXcgY2RrLkNmbk91dHB1dCh0aGlzLCAnaW50ZXJuYWwtaXAnLCB7XG4gICAgICB2YWx1ZTogaW5zdGFuY2UuaW5zdGFuY2VQcml2YXRlSXAsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
|