aws-ec2-instance-running-scheduler 3.0.9 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +4 -5
- package/README.md +7 -6
- package/assets/funcs/running-scheduler.lambda/index.js +221 -12
- package/lib/constructs/ec2-instance-running-scheduler.js +1 -1
- package/lib/funcs/running-scheduler.lambda.d.ts +1 -1
- package/lib/funcs/running-scheduler.lambda.js +84 -14
- package/lib/stacks/ec2-instance-running-schedule-stack.js +1 -1
- package/package.json +14 -5
package/.jsii
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"author": {
|
|
3
3
|
"email": "yicr@users.noreply.github.com",
|
|
4
4
|
"name": "yicr",
|
|
5
|
-
"organization": true,
|
|
6
5
|
"roles": [
|
|
7
6
|
"author"
|
|
8
7
|
]
|
|
@@ -8441,7 +8440,7 @@
|
|
|
8441
8440
|
"stability": "stable"
|
|
8442
8441
|
},
|
|
8443
8442
|
"homepage": "https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler.git",
|
|
8444
|
-
"jsiiVersion": "5.9.
|
|
8443
|
+
"jsiiVersion": "5.9.36 (build 27873df)",
|
|
8445
8444
|
"keywords": [
|
|
8446
8445
|
"auto",
|
|
8447
8446
|
"aws",
|
|
@@ -8463,7 +8462,7 @@
|
|
|
8463
8462
|
},
|
|
8464
8463
|
"name": "aws-ec2-instance-running-scheduler",
|
|
8465
8464
|
"readme": {
|
|
8466
|
-
"markdown": "# AWS EC2 Instance Running Scheduler\n\n[](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/blob/main/LICENSE)\n[](https://www.npmjs.com/package/aws-ec2-instance-running-scheduler)\n[](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/actions/workflows/release.yml)\n[](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/releases)\n\n[](https://constructs.dev/packages/aws-ec2-instance-running-scheduler)\n\nAWS CDK construct that starts and stops EC2 instances on a cron schedule using **EventBridge Scheduler** and a **Durable Execution Lambda**. The handler discovers instances with the **Resource Groups Tagging API**, runs start/stop and **polls until the instance reaches the target state** (durable `step` / `wait`), processes **multiple instances in parallel** (bounded concurrency), and posts **Slack** summary and per-instance thread messages using a secret from **Secrets Manager
|
|
8465
|
+
"markdown": "# AWS EC2 Instance Running Scheduler\n\n[](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/blob/main/LICENSE)\n[](https://www.npmjs.com/package/aws-ec2-instance-running-scheduler)\n[](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/actions/workflows/release.yml)\n[](https://github.com/gammarers-aws-cdk-constructs/aws-ec2-instance-running-scheduler/releases)\n\n[](https://constructs.dev/packages/aws-ec2-instance-running-scheduler)\n\nAWS CDK construct that starts and stops EC2 instances on a cron schedule using **EventBridge Scheduler** and a **Durable Execution Lambda**. The handler discovers instances with the **Resource Groups Tagging API**, runs start/stop and **polls until the instance reaches the target state** (durable `step` / `wait`), processes **multiple instances in parallel** (bounded concurrency), and posts **Slack** summary and per-instance thread messages using a secret from **Secrets Manager**. The Lambda emits **structured application logs** (invocation, EC2 transitions, Slack steps, completion) alongside JSON platform logs.\n\n## Features\n\n- **Tag-based targeting** – Select EC2 instances by tag key and values (e.g. `Schedule` / `YES`) via `tag:GetResources`.\n- **EventBridge Scheduler** – Separate cron rules for start and stop, with per-rule timezone (`aws-cdk-lib` `TimeZone`).\n- **Durable Lambda** – One Lambda with AWS Lambda Durable Execution (`step`, `wait`, `map`, child contexts per instance) for long-running workflows without Step Functions.\n- **Stable-state polling** – After start/stop, the function waits and re-describes instances until `running` (start mode) or `stopped` (stop mode), or until a terminal error.\n- **Slack notifications** – Required for a successful run: parent message plus threaded updates per instance; credentials come from Secrets Manager (`token` and `channel` JSON). The secret name is passed as **`SLACK_SECRET_NAME`** on the function (from `secrets.slackSecretName`) and validated at runtime via **safe-env-getter**.\n- **Structured logging** – The handler uses the durable execution **`ctx.logger`** for traceable JSON application logs (e.g. invocation, describe/start/stop/wait loops, target count, Slack posts, errors before instance state failures).\n- **Scheduling toggle** – Enable or disable both schedules without removing the stack (`enableScheduling`).\n- **Configurable schedules** – Optional cron overrides for start and stop (`minute`, `hour`, `week`, `timezone`); sensible defaults if omitted.\n- **IAM and observability** – EC2 and tagging API permissions, Slack secret read grant, **Parameters and Secrets Lambda Extension** (configured on the function for secret access patterns), JSON logging with configurable system/application levels, and a dedicated log group (construct defaults).\n\n## Installation\n\n**npm**\n\n```bash\nnpm install aws-ec2-instance-running-scheduler\n```\n\n**yarn**\n\n```bash\nyarn add aws-ec2-instance-running-scheduler\n```\n\n**pnpm**\n\n```bash\npnpm add aws-ec2-instance-running-scheduler\n```\n\n## Usage\n\nUse the **construct** `EC2InstanceRunningScheduler` when embedding the scheduler in an existing stack or other CDK scope.\n\n```typescript\nimport * as cdk from 'aws-cdk-lib';\nimport { TimeZone } from 'aws-cdk-lib';\nimport { EC2InstanceRunningScheduler } from 'aws-ec2-instance-running-scheduler';\n\nconst app = new cdk.App();\nconst stack = new cdk.Stack(app, 'MyStack');\n\nnew EC2InstanceRunningScheduler(stack, 'EC2InstanceRunningScheduler', {\n targetResource: {\n tagKey: 'Schedule',\n tagValues: ['YES'],\n },\n secrets: {\n slackSecretName: 'my-slack-secret',\n },\n startSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '55',\n hour: '8',\n week: 'MON-FRI',\n },\n stopSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '5',\n hour: '19',\n week: 'MON-FRI',\n },\n enableScheduling: true,\n});\n```\n\nUse the **stack** `EC2InstanceRunningScheduleStack` when deploying the scheduler as its own stack. It accepts the **same scheduler options** as the construct (plus standard `StackProps` such as `env`).\n\n```typescript\nimport * as cdk from 'aws-cdk-lib';\nimport { TimeZone } from 'aws-cdk-lib';\nimport { EC2InstanceRunningScheduleStack } from 'aws-ec2-instance-running-scheduler';\n\nconst app = new cdk.App();\n\nnew EC2InstanceRunningScheduleStack(app, 'EC2InstanceRunningScheduleStack', {\n targetResource: {\n tagKey: 'Schedule',\n tagValues: ['YES'],\n },\n secrets: {\n slackSecretName: 'my-slack-secret',\n },\n startSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '55',\n hour: '8',\n week: 'MON-FRI',\n },\n stopSchedule: {\n timezone: TimeZone.ASIA_TOKYO,\n minute: '5',\n hour: '19',\n week: 'MON-FRI',\n },\n enableScheduling: true,\n});\n```\n\nEventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues`, and `Params.Mode` (`Start` or `Stop`); the construct wires this for you. The function environment includes **`SLACK_SECRET_NAME`** set to `secrets.slackSecretName`.\n\n## Options\n\nThese options apply to **`EC2InstanceRunningScheduler`** and to **`EC2InstanceRunningScheduleStack`** (stack props include them alongside `StackProps`).\n\n| Option | Type | Required | Description |\n|--------|------|----------|-------------|\n| `targetResource` | `TargetResource` | Yes | Tag key and values used to select EC2 instances. |\n| `secrets` | `Secrets` | Yes | Identifies the Secrets Manager secret used for Slack (`slackSecretName`). |\n| `startSchedule` | `Schedule` | No | Cron for starting instances (default: `50 7 ? * MON-FRI *` in `Etc/UTC`). |\n| `stopSchedule` | `Schedule` | No | Cron for stopping instances (default: `5 19 ? * MON-FRI *` in `Etc/UTC`). |\n| `enableScheduling` | `boolean` | No | Whether both scheduler rules are enabled (default: `true`). |\n\n### TargetResource\n\n- `tagKey` – Tag key used to select instances (e.g. `Schedule`).\n- `tagValues` – Tag values that must match (e.g. `['YES']`).\n\n### Schedule\n\n- `timezone` – `TimeZone` from `aws-cdk-lib` (e.g. `TimeZone.ASIA_TOKYO`, `TimeZone.ETC_UTC`).\n- `minute` – Cron minute (`0`–`59`).\n- `hour` – Cron hour (`0`–`23`).\n- `week` – Cron day-of-week field (e.g. `MON-FRI`).\n\n### Secrets\n\n- `slackSecretName` – Name of the AWS Secrets Manager secret. The Lambda expects JSON with **`token`** (Slack bot token) and **`channel`** (channel ID or name for `chat.postMessage`). The construct sets **`SLACK_SECRET_NAME`** on the function to this value; the handler reads and validates it at runtime (via **safe-env-getter**).\n\n## Requirements\n\n- **Node.js** ≥ 20.0.0 (for developing or synthesizing CDK apps that depend on this package).\n- **aws-cdk-lib** ^2.232.0 and **constructs** ^10.5.1 (peer dependencies).\n- **AWS** – EventBridge Scheduler; Lambda with **Durable Execution** (requires **Node.js 22+** in the deployment region—runtime is the latest Node.js available in the region per the construct), a **live alias**, **Parameters and Secrets Lambda Extension**; EC2 (describe/start/stop); Resource Groups Tagging API; Secrets Manager. The deployed function uses **arm64**, Durable Execution–compatible IAM and settings, and a bundled handler that loads secrets via **aws-lambda-secret-fetcher**.\n\n## License\n\nThis project is licensed under the Apache-2.0 License.\n"
|
|
8467
8466
|
},
|
|
8468
8467
|
"repository": {
|
|
8469
8468
|
"type": "git",
|
|
@@ -8969,6 +8968,6 @@
|
|
|
8969
8968
|
"symbolId": "src/constructs/ec2-instance-running-scheduler:TargetResource"
|
|
8970
8969
|
}
|
|
8971
8970
|
},
|
|
8972
|
-
"version": "3.0
|
|
8973
|
-
"fingerprint": "
|
|
8971
|
+
"version": "3.1.0",
|
|
8972
|
+
"fingerprint": "d3YHyiyERSOnDctHGkrNVgZh16Hoxj/djXjCfTeXMyc="
|
|
8974
8973
|
}
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
[](https://constructs.dev/packages/aws-ec2-instance-running-scheduler)
|
|
9
9
|
|
|
10
|
-
AWS CDK construct that starts and stops EC2 instances on a cron schedule using **EventBridge Scheduler** and a **Durable Execution Lambda**. The handler discovers instances with the **Resource Groups Tagging API**, runs start/stop and **polls until the instance reaches the target state** (durable `step` / `wait`), processes **multiple instances in parallel** (bounded concurrency), and posts **Slack** summary and per-instance thread messages using a secret from **Secrets Manager**.
|
|
10
|
+
AWS CDK construct that starts and stops EC2 instances on a cron schedule using **EventBridge Scheduler** and a **Durable Execution Lambda**. The handler discovers instances with the **Resource Groups Tagging API**, runs start/stop and **polls until the instance reaches the target state** (durable `step` / `wait`), processes **multiple instances in parallel** (bounded concurrency), and posts **Slack** summary and per-instance thread messages using a secret from **Secrets Manager**. The Lambda emits **structured application logs** (invocation, EC2 transitions, Slack steps, completion) alongside JSON platform logs.
|
|
11
11
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
@@ -15,10 +15,11 @@ AWS CDK construct that starts and stops EC2 instances on a cron schedule using *
|
|
|
15
15
|
- **EventBridge Scheduler** – Separate cron rules for start and stop, with per-rule timezone (`aws-cdk-lib` `TimeZone`).
|
|
16
16
|
- **Durable Lambda** – One Lambda with AWS Lambda Durable Execution (`step`, `wait`, `map`, child contexts per instance) for long-running workflows without Step Functions.
|
|
17
17
|
- **Stable-state polling** – After start/stop, the function waits and re-describes instances until `running` (start mode) or `stopped` (stop mode), or until a terminal error.
|
|
18
|
-
- **Slack notifications** – Required for a successful run: parent message plus threaded updates per instance; credentials come from Secrets Manager (`token` and `channel` JSON).
|
|
18
|
+
- **Slack notifications** – Required for a successful run: parent message plus threaded updates per instance; credentials come from Secrets Manager (`token` and `channel` JSON). The secret name is passed as **`SLACK_SECRET_NAME`** on the function (from `secrets.slackSecretName`) and validated at runtime via **safe-env-getter**.
|
|
19
|
+
- **Structured logging** – The handler uses the durable execution **`ctx.logger`** for traceable JSON application logs (e.g. invocation, describe/start/stop/wait loops, target count, Slack posts, errors before instance state failures).
|
|
19
20
|
- **Scheduling toggle** – Enable or disable both schedules without removing the stack (`enableScheduling`).
|
|
20
21
|
- **Configurable schedules** – Optional cron overrides for start and stop (`minute`, `hour`, `week`, `timezone`); sensible defaults if omitted.
|
|
21
|
-
- **IAM and observability** – EC2 and tagging API permissions, Slack secret read grant, JSON logging, and a dedicated log group (construct defaults).
|
|
22
|
+
- **IAM and observability** – EC2 and tagging API permissions, Slack secret read grant, **Parameters and Secrets Lambda Extension** (configured on the function for secret access patterns), JSON logging with configurable system/application levels, and a dedicated log group (construct defaults).
|
|
22
23
|
|
|
23
24
|
## Installation
|
|
24
25
|
|
|
@@ -109,7 +110,7 @@ new EC2InstanceRunningScheduleStack(app, 'EC2InstanceRunningScheduleStack', {
|
|
|
109
110
|
});
|
|
110
111
|
```
|
|
111
112
|
|
|
112
|
-
EventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues`, and `Params.Mode` (`Start` or `Stop`); the construct wires this for you.
|
|
113
|
+
EventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues`, and `Params.Mode` (`Start` or `Stop`); the construct wires this for you. The function environment includes **`SLACK_SECRET_NAME`** set to `secrets.slackSecretName`.
|
|
113
114
|
|
|
114
115
|
## Options
|
|
115
116
|
|
|
@@ -137,13 +138,13 @@ These options apply to **`EC2InstanceRunningScheduler`** and to **`EC2InstanceRu
|
|
|
137
138
|
|
|
138
139
|
### Secrets
|
|
139
140
|
|
|
140
|
-
- `slackSecretName` – Name of the AWS Secrets Manager secret. The Lambda expects JSON with **`token`** (Slack bot token) and **`channel`** (channel ID or name for `chat.postMessage`).
|
|
141
|
+
- `slackSecretName` – Name of the AWS Secrets Manager secret. The Lambda expects JSON with **`token`** (Slack bot token) and **`channel`** (channel ID or name for `chat.postMessage`). The construct sets **`SLACK_SECRET_NAME`** on the function to this value; the handler reads and validates it at runtime (via **safe-env-getter**).
|
|
141
142
|
|
|
142
143
|
## Requirements
|
|
143
144
|
|
|
144
145
|
- **Node.js** ≥ 20.0.0 (for developing or synthesizing CDK apps that depend on this package).
|
|
145
146
|
- **aws-cdk-lib** ^2.232.0 and **constructs** ^10.5.1 (peer dependencies).
|
|
146
|
-
- **AWS** – EventBridge Scheduler; Lambda with **Durable Execution**
|
|
147
|
+
- **AWS** – EventBridge Scheduler; Lambda with **Durable Execution** (requires **Node.js 22+** in the deployment region—runtime is the latest Node.js available in the region per the construct), a **live alias**, **Parameters and Secrets Lambda Extension**; EC2 (describe/start/stop); Resource Groups Tagging API; Secrets Manager. The deployed function uses **arm64**, Durable Execution–compatible IAM and settings, and a bundled handler that loads secrets via **aws-lambda-secret-fetcher**.
|
|
147
148
|
|
|
148
149
|
## License
|
|
149
150
|
|
|
@@ -18968,6 +18968,146 @@ var require_lib2 = __commonJS({
|
|
|
18968
18968
|
}
|
|
18969
18969
|
});
|
|
18970
18970
|
|
|
18971
|
+
// node_modules/safe-env-getter/lib/index.js
|
|
18972
|
+
var require_lib3 = __commonJS({
|
|
18973
|
+
"node_modules/safe-env-getter/lib/index.js"(exports2) {
|
|
18974
|
+
"use strict";
|
|
18975
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
18976
|
+
exports2.SafeEnvGetter = exports2.SafeEnvType = exports2.SafeEnvGetterValidationError = exports2.SafeEnvGetterError = void 0;
|
|
18977
|
+
var SafeEnvGetterError = class extends Error {
|
|
18978
|
+
constructor(message) {
|
|
18979
|
+
super(message);
|
|
18980
|
+
this.name = "SafeEnvGetterError";
|
|
18981
|
+
}
|
|
18982
|
+
};
|
|
18983
|
+
exports2.SafeEnvGetterError = SafeEnvGetterError;
|
|
18984
|
+
var SafeEnvGetterValidationError = class _SafeEnvGetterValidationError extends SafeEnvGetterError {
|
|
18985
|
+
/**
|
|
18986
|
+
* Formats validation errors into a human-readable error message.
|
|
18987
|
+
*/
|
|
18988
|
+
static format(errors) {
|
|
18989
|
+
const lines = errors.map((e) => `- ${e.key}: ${e.message}${e.raw == null ? "" : ` (raw="${e.raw}")`}`);
|
|
18990
|
+
return `Invalid environment variables (${errors.length}):
|
|
18991
|
+
${lines.join("\n")}`;
|
|
18992
|
+
}
|
|
18993
|
+
/**
|
|
18994
|
+
* Creates a new validation error from one or more `SafeEnvError` entries.
|
|
18995
|
+
*/
|
|
18996
|
+
constructor(errors) {
|
|
18997
|
+
const msg = _SafeEnvGetterValidationError.format(errors);
|
|
18998
|
+
super(msg);
|
|
18999
|
+
this.name = "SafeEnvGetterValidationError";
|
|
19000
|
+
this.errors = errors;
|
|
19001
|
+
this.keys = errors.map((e) => e.key);
|
|
19002
|
+
}
|
|
19003
|
+
};
|
|
19004
|
+
exports2.SafeEnvGetterValidationError = SafeEnvGetterValidationError;
|
|
19005
|
+
exports2.SafeEnvType = {
|
|
19006
|
+
/** Spec for a string value. */
|
|
19007
|
+
String: { type: "string" },
|
|
19008
|
+
/** Spec for a numeric value. */
|
|
19009
|
+
Number: { type: "number" },
|
|
19010
|
+
/** Spec for a boolean value (1/true/yes/on → true). */
|
|
19011
|
+
Boolean: { type: "boolean" },
|
|
19012
|
+
/**
|
|
19013
|
+
* Returns a spec that restricts the value to one of the given choices.
|
|
19014
|
+
* @param choices - Allowed string literals.
|
|
19015
|
+
* @returns Enum spec for use with `getEnv`.
|
|
19016
|
+
*/
|
|
19017
|
+
Enum: (choices) => ({ type: "enum", choices })
|
|
19018
|
+
};
|
|
19019
|
+
function getEnv(key, spec = exports2.SafeEnvType.String, options) {
|
|
19020
|
+
const raw = process.env[key];
|
|
19021
|
+
const defaultValue = options?.default;
|
|
19022
|
+
const hasDefault = defaultValue !== void 0;
|
|
19023
|
+
if (raw == null || raw === "") {
|
|
19024
|
+
if (!hasDefault) {
|
|
19025
|
+
throw new SafeEnvGetterValidationError([
|
|
19026
|
+
{ key, message: `Missing required environment variable: ${key}`, raw, kind: "missing" }
|
|
19027
|
+
]);
|
|
19028
|
+
}
|
|
19029
|
+
return defaultValue;
|
|
19030
|
+
}
|
|
19031
|
+
switch (spec.type) {
|
|
19032
|
+
case "number": {
|
|
19033
|
+
const n = Number(raw);
|
|
19034
|
+
if (Number.isNaN(n)) {
|
|
19035
|
+
throw new SafeEnvGetterValidationError([
|
|
19036
|
+
{ key, message: `Env ${key}: expected number, got "${raw}"`, raw, kind: "invalid_number" }
|
|
19037
|
+
]);
|
|
19038
|
+
}
|
|
19039
|
+
return n;
|
|
19040
|
+
}
|
|
19041
|
+
case "boolean":
|
|
19042
|
+
return /^(1|true|yes|on)$/i.test(raw) ? true : false;
|
|
19043
|
+
case "enum":
|
|
19044
|
+
if (!spec.choices.includes(raw)) {
|
|
19045
|
+
throw new SafeEnvGetterValidationError([
|
|
19046
|
+
{ key, message: `Env ${key}: must be one of [${spec.choices.join(", ")}]`, raw, kind: "invalid_enum" }
|
|
19047
|
+
]);
|
|
19048
|
+
}
|
|
19049
|
+
return raw;
|
|
19050
|
+
default:
|
|
19051
|
+
return raw;
|
|
19052
|
+
}
|
|
19053
|
+
}
|
|
19054
|
+
var getEnvs = (schema) => {
|
|
19055
|
+
const envs = {};
|
|
19056
|
+
const errors = [];
|
|
19057
|
+
for (const key of Object.keys(schema)) {
|
|
19058
|
+
const entry = schema[key];
|
|
19059
|
+
const spec = Array.isArray(entry) ? entry[0] : entry;
|
|
19060
|
+
const options = Array.isArray(entry) ? entry[1] : void 0;
|
|
19061
|
+
const raw = process.env[key];
|
|
19062
|
+
const defaultValue = options?.default;
|
|
19063
|
+
const hasDefault = defaultValue !== void 0;
|
|
19064
|
+
if (raw == null || raw === "") {
|
|
19065
|
+
if (!hasDefault) {
|
|
19066
|
+
errors.push({ key, message: `Missing required environment variable: ${key}`, raw, kind: "missing" });
|
|
19067
|
+
continue;
|
|
19068
|
+
}
|
|
19069
|
+
envs[key] = defaultValue;
|
|
19070
|
+
continue;
|
|
19071
|
+
}
|
|
19072
|
+
if (spec.type === "number") {
|
|
19073
|
+
const n = Number(raw);
|
|
19074
|
+
if (Number.isNaN(n)) {
|
|
19075
|
+
errors.push({ key, message: `Env ${key}: expected number, got "${raw}"`, raw, kind: "invalid_number" });
|
|
19076
|
+
continue;
|
|
19077
|
+
}
|
|
19078
|
+
envs[key] = n;
|
|
19079
|
+
continue;
|
|
19080
|
+
}
|
|
19081
|
+
if (spec.type === "boolean") {
|
|
19082
|
+
envs[key] = /^(1|true|yes|on)$/i.test(raw) ? true : false;
|
|
19083
|
+
continue;
|
|
19084
|
+
}
|
|
19085
|
+
if (spec.type === "enum") {
|
|
19086
|
+
if (!spec.choices.includes(raw)) {
|
|
19087
|
+
errors.push({
|
|
19088
|
+
key,
|
|
19089
|
+
message: `Env ${key}: must be one of [${spec.choices.join(", ")}]`,
|
|
19090
|
+
raw,
|
|
19091
|
+
kind: "invalid_enum"
|
|
19092
|
+
});
|
|
19093
|
+
continue;
|
|
19094
|
+
}
|
|
19095
|
+
envs[key] = raw;
|
|
19096
|
+
continue;
|
|
19097
|
+
}
|
|
19098
|
+
envs[key] = raw;
|
|
19099
|
+
}
|
|
19100
|
+
if (errors.length > 0)
|
|
19101
|
+
throw new SafeEnvGetterValidationError(errors);
|
|
19102
|
+
return envs;
|
|
19103
|
+
};
|
|
19104
|
+
exports2.SafeEnvGetter = {
|
|
19105
|
+
getEnv,
|
|
19106
|
+
getEnvs
|
|
19107
|
+
};
|
|
19108
|
+
}
|
|
19109
|
+
});
|
|
19110
|
+
|
|
18971
19111
|
// src/funcs/running-scheduler.lambda.ts
|
|
18972
19112
|
var running_scheduler_lambda_exports = {};
|
|
18973
19113
|
__export(running_scheduler_lambda_exports, {
|
|
@@ -22469,6 +22609,7 @@ var import_client_ec2 = require("@aws-sdk/client-ec2");
|
|
|
22469
22609
|
var import_client_resource_groups_tagging_api = require("@aws-sdk/client-resource-groups-tagging-api");
|
|
22470
22610
|
var import_web_api = __toESM(require_dist4());
|
|
22471
22611
|
var import_aws_lambda_secret_fetcher = __toESM(require_lib2());
|
|
22612
|
+
var import_safe_env_getter = __toESM(require_lib3());
|
|
22472
22613
|
|
|
22473
22614
|
// src/funcs/running-scheduler-predicates.ts
|
|
22474
22615
|
var isDesiredStableState = (mode, currentState) => mode === "Start" && currentState === "running" || mode === "Stop" && currentState === "stopped";
|
|
@@ -22490,6 +22631,13 @@ var processOneResource = async (ctx, targetResource, params, resourceIndex) => {
|
|
|
22490
22631
|
const account = arnParts[4] ?? "";
|
|
22491
22632
|
const region = arnParts[3] ?? "";
|
|
22492
22633
|
const stepPrefix = `resource-${resourceIndex}-${identifier}`;
|
|
22634
|
+
ctx.logger.info("processOneResource: start", {
|
|
22635
|
+
resourceIndex,
|
|
22636
|
+
identifier,
|
|
22637
|
+
region,
|
|
22638
|
+
account,
|
|
22639
|
+
mode: params.Mode
|
|
22640
|
+
});
|
|
22493
22641
|
let loopCount = 0;
|
|
22494
22642
|
let currentState = "";
|
|
22495
22643
|
do {
|
|
@@ -22498,21 +22646,37 @@ var processOneResource = async (ctx, targetResource, params, resourceIndex) => {
|
|
|
22498
22646
|
const out = await ec2.send(new import_client_ec2.DescribeInstancesCommand({ InstanceIds: [identifier] }));
|
|
22499
22647
|
return out.Reservations?.[0]?.Instances?.[0]?.State?.Name ?? "unknown";
|
|
22500
22648
|
});
|
|
22649
|
+
ctx.logger.info("processOneResource: described", {
|
|
22650
|
+
identifier,
|
|
22651
|
+
loopCount,
|
|
22652
|
+
currentState,
|
|
22653
|
+
mode: params.Mode
|
|
22654
|
+
});
|
|
22501
22655
|
const mode = params.Mode;
|
|
22502
22656
|
if (mode === "Start" && currentState === "stopped") {
|
|
22657
|
+
ctx.logger.info("processOneResource: starting instance", { identifier, loopCount });
|
|
22503
22658
|
await ctx.step(`${stepPrefix}-start-${loopCount}`, async () => {
|
|
22504
22659
|
const ec2 = new import_client_ec2.EC2Client({});
|
|
22505
22660
|
await ec2.send(new import_client_ec2.StartInstancesCommand({ InstanceIds: [identifier] }));
|
|
22506
22661
|
});
|
|
22662
|
+
ctx.logger.info("processOneResource: wait after start", {
|
|
22663
|
+
identifier,
|
|
22664
|
+
seconds: STATUS_CHANGE_WAIT_SECONDS
|
|
22665
|
+
});
|
|
22507
22666
|
await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
|
|
22508
22667
|
loopCount += 1;
|
|
22509
22668
|
continue;
|
|
22510
22669
|
}
|
|
22511
22670
|
if (mode === "Stop" && currentState === "running") {
|
|
22671
|
+
ctx.logger.info("processOneResource: stopping instance", { identifier, loopCount });
|
|
22512
22672
|
await ctx.step(`${stepPrefix}-stop-${loopCount}`, async () => {
|
|
22513
22673
|
const ec2 = new import_client_ec2.EC2Client({});
|
|
22514
22674
|
await ec2.send(new import_client_ec2.StopInstancesCommand({ InstanceIds: [identifier] }));
|
|
22515
22675
|
});
|
|
22676
|
+
ctx.logger.info("processOneResource: wait after stop", {
|
|
22677
|
+
identifier,
|
|
22678
|
+
seconds: STATUS_CHANGE_WAIT_SECONDS
|
|
22679
|
+
});
|
|
22516
22680
|
await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
|
|
22517
22681
|
loopCount += 1;
|
|
22518
22682
|
continue;
|
|
@@ -22520,13 +22684,32 @@ var processOneResource = async (ctx, targetResource, params, resourceIndex) => {
|
|
|
22520
22684
|
if (!isDesiredStableState(mode, currentState)) {
|
|
22521
22685
|
const transitioning = mode === "Start" && currentState === "pending" || mode === "Stop" && (currentState === "stopping" || currentState === "shutting-down");
|
|
22522
22686
|
if (transitioning) {
|
|
22687
|
+
ctx.logger.info("processOneResource: wait while transitioning", {
|
|
22688
|
+
identifier,
|
|
22689
|
+
loopCount,
|
|
22690
|
+
currentState,
|
|
22691
|
+
mode,
|
|
22692
|
+
seconds: STATUS_CHANGE_WAIT_SECONDS
|
|
22693
|
+
});
|
|
22523
22694
|
await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
|
|
22524
22695
|
loopCount += 1;
|
|
22525
22696
|
continue;
|
|
22526
22697
|
}
|
|
22698
|
+
ctx.logger.error("processOneResource: unexpected state", {
|
|
22699
|
+
identifier,
|
|
22700
|
+
mode,
|
|
22701
|
+
currentState,
|
|
22702
|
+
loopCount
|
|
22703
|
+
});
|
|
22527
22704
|
throw new Error(`instance status fail: mode=${mode} currentState=${currentState}`);
|
|
22528
22705
|
}
|
|
22529
22706
|
} while (!isDesiredStableState(params.Mode, currentState));
|
|
22707
|
+
ctx.logger.info("processOneResource: reached desired stable state", {
|
|
22708
|
+
identifier,
|
|
22709
|
+
finalState: currentState,
|
|
22710
|
+
mode: params.Mode,
|
|
22711
|
+
loopCount
|
|
22712
|
+
});
|
|
22530
22713
|
return {
|
|
22531
22714
|
identifier,
|
|
22532
22715
|
account,
|
|
@@ -22535,22 +22718,26 @@ var processOneResource = async (ctx, targetResource, params, resourceIndex) => {
|
|
|
22535
22718
|
status: currentState
|
|
22536
22719
|
};
|
|
22537
22720
|
};
|
|
22538
|
-
var handler = withDurableExecution(async (event,
|
|
22721
|
+
var handler = withDurableExecution(async (event, ctx) => {
|
|
22539
22722
|
const params = event.Params;
|
|
22723
|
+
ctx.logger.info("running-scheduler: invocation", {
|
|
22724
|
+
mode: params?.Mode,
|
|
22725
|
+
tagKey: params?.TagKey,
|
|
22726
|
+
tagValueCount: params?.TagValues?.length ?? 0
|
|
22727
|
+
});
|
|
22540
22728
|
if (!params?.TagKey || !params?.TagValues || !params?.Mode) {
|
|
22541
22729
|
throw new Error("Invalid event: Params.TagKey, Params.TagValues, Params.Mode are required.");
|
|
22542
22730
|
}
|
|
22543
|
-
const slackSecretName =
|
|
22544
|
-
|
|
22545
|
-
|
|
22546
|
-
}
|
|
22547
|
-
const slackSecretValue = await context.step("fetch-slack-secret", async () => {
|
|
22731
|
+
const slackSecretName = import_safe_env_getter.SafeEnvGetter.getEnv("SLACK_SECRET_NAME");
|
|
22732
|
+
const slackSecretValue = await ctx.step("fetch-slack-secret", async () => {
|
|
22733
|
+
ctx.logger.info("running-scheduler: fetching Slack secret", { secretName: slackSecretName });
|
|
22548
22734
|
return import_aws_lambda_secret_fetcher.secretFetcher.getSecretValue(slackSecretName);
|
|
22549
22735
|
});
|
|
22736
|
+
ctx.logger.info("running-scheduler: Slack secret loaded");
|
|
22550
22737
|
if (!slackSecretValue?.token || !slackSecretValue?.channel) {
|
|
22551
22738
|
throw new Error("Slack secret must contain token and channel.");
|
|
22552
22739
|
}
|
|
22553
|
-
const targetResources = await
|
|
22740
|
+
const targetResources = await ctx.step("get-target-resources", async () => {
|
|
22554
22741
|
const client2 = new import_client_resource_groups_tagging_api.ResourceGroupsTaggingAPIClient({});
|
|
22555
22742
|
const result = await client2.send(
|
|
22556
22743
|
new import_client_resource_groups_tagging_api.GetResourcesCommand({
|
|
@@ -22558,28 +22745,46 @@ var handler = withDurableExecution(async (event, context) => {
|
|
|
22558
22745
|
TagFilters: [{ Key: params.TagKey, Values: params.TagValues }]
|
|
22559
22746
|
})
|
|
22560
22747
|
);
|
|
22561
|
-
|
|
22748
|
+
const arns = (result.ResourceTagMappingList ?? []).map((m) => m.ResourceARN).filter((arn) => arn != null);
|
|
22749
|
+
ctx.logger.info("running-scheduler: get-target-resources done", { count: arns.length });
|
|
22750
|
+
return arns;
|
|
22562
22751
|
});
|
|
22563
22752
|
if (targetResources.length === 0) {
|
|
22753
|
+
ctx.logger.info("running-scheduler: no matching instances", { tagKey: params.TagKey });
|
|
22564
22754
|
return { status: "TargetResourcesNotFound" };
|
|
22565
22755
|
}
|
|
22566
22756
|
const client = new import_web_api.WebClient(slackSecretValue.token);
|
|
22567
22757
|
const channel = slackSecretValue.channel;
|
|
22568
|
-
|
|
22758
|
+
ctx.logger.info("running-scheduler: posting parent Slack message", {
|
|
22759
|
+
instanceCount: targetResources.length
|
|
22760
|
+
});
|
|
22761
|
+
const slackParentMessageResult = await ctx.step("post-slack-messages", async () => {
|
|
22569
22762
|
return client.chat.postMessage({
|
|
22570
22763
|
channel,
|
|
22571
22764
|
text: `${params.Mode === "Start" ? "\u{1F606} Starts" : "\u{1F971} Stops"} the scheduled EC2 Instance.`
|
|
22572
22765
|
});
|
|
22573
22766
|
});
|
|
22574
|
-
|
|
22767
|
+
ctx.logger.info("running-scheduler: parent Slack message posted", {
|
|
22768
|
+
threadTs: slackParentMessageResult?.ts ?? null
|
|
22769
|
+
});
|
|
22770
|
+
ctx.logger.info("running-scheduler: starting parallel instance processing", {
|
|
22771
|
+
count: targetResources.length,
|
|
22772
|
+
maxConcurrency: 10
|
|
22773
|
+
});
|
|
22774
|
+
const results = await ctx.map(
|
|
22575
22775
|
targetResources,
|
|
22576
22776
|
// async (ctx: DurableContext, targetResource: string, index: number) =>
|
|
22577
22777
|
// ctx.step(`process-resource-${index}`, async () =>
|
|
22578
22778
|
// processOneResource(ctx, targetResource, params, index),
|
|
22579
22779
|
// ),
|
|
22580
|
-
async (
|
|
22581
|
-
return
|
|
22780
|
+
async (mapCtx, targetResource, index) => {
|
|
22781
|
+
return mapCtx.runInChildContext(`resource-${index}`, async (childCtx) => {
|
|
22582
22782
|
const result = await processOneResource(childCtx, targetResource, params, index);
|
|
22783
|
+
childCtx.logger.info("running-scheduler: posting thread Slack message", {
|
|
22784
|
+
index,
|
|
22785
|
+
identifier: result.identifier,
|
|
22786
|
+
status: result.status
|
|
22787
|
+
});
|
|
22583
22788
|
await childCtx.step("post-slack-child-messages", async () => {
|
|
22584
22789
|
const display = getStateDisplay(result.status);
|
|
22585
22790
|
return client.chat.postMessage({
|
|
@@ -22605,6 +22810,10 @@ var handler = withDurableExecution(async (event, context) => {
|
|
|
22605
22810
|
{ maxConcurrency: 10 }
|
|
22606
22811
|
);
|
|
22607
22812
|
const resultList = Array.isArray(results) ? results : [];
|
|
22813
|
+
ctx.logger.info("running-scheduler: completed", {
|
|
22814
|
+
processed: targetResources.length,
|
|
22815
|
+
resultCount: resultList.length
|
|
22816
|
+
});
|
|
22608
22817
|
return {
|
|
22609
22818
|
status: "Completed",
|
|
22610
22819
|
processed: targetResources.length,
|
|
@@ -139,5 +139,5 @@ class EC2InstanceRunningScheduler extends constructs_1.Construct {
|
|
|
139
139
|
}
|
|
140
140
|
exports.EC2InstanceRunningScheduler = EC2InstanceRunningScheduler;
|
|
141
141
|
_a = JSII_RTTI_SYMBOL_1;
|
|
142
|
-
EC2InstanceRunningScheduler[_a] = { fqn: "aws-ec2-instance-running-scheduler.EC2InstanceRunningScheduler", version: "3.0
|
|
142
|
+
EC2InstanceRunningScheduler[_a] = { fqn: "aws-ec2-instance-running-scheduler.EC2InstanceRunningScheduler", version: "3.1.0" };
|
|
143
143
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWMyLWluc3RhbmNlLXJ1bm5pbmctc2NoZWR1bGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnN0cnVjdHMvZWMyLWluc3RhbmNlLXJ1bm5pbmctc2NoZWR1bGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkNBQWdFO0FBQ2hFLDJDQUEyQztBQUMzQyxpREFBaUQ7QUFDakQsNkNBQTZDO0FBQzdDLHVEQUF1RDtBQUN2RCw2REFBNkQ7QUFDN0QsdUVBQXdEO0FBQ3hELDJDQUF1QztBQUN2QyxvRkFBK0U7QUFrRC9FOzs7OztHQUtHO0FBQ0gsTUFBYSwyQkFBNEIsU0FBUSxzQkFBUztJQUN4RDs7Ozs7O09BTUc7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXVDO1FBQy9FLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxXQUFXLEdBQUcsMkJBQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFaEcsbUdBQW1HO1FBQ25HLDBDQUEwQztRQUMxQyxNQUFNLHVCQUF1QixHQUFHLElBQUkscURBQXdCLENBQUMsSUFBSSxFQUFFLDBCQUEwQixFQUFFO1lBQzdGLFdBQVcsRUFBRSwyRUFBMkU7WUFDeEYsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTTtZQUN4QyxPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzdCLFVBQVUsRUFBRSxHQUFHO1lBQ2YsYUFBYSxFQUFFLENBQUM7WUFDaEIsYUFBYSxFQUFFO2dCQUNiLGdCQUFnQixFQUFFLHNCQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFDbkMsZUFBZSxFQUFFLHNCQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzthQUNsQztZQUNELFdBQVcsRUFBRTtnQkFD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QUFFO3dCQUNOLE1BQU0sRUFBRSxLQUFLLENBQUMsY0FBYyxDQUFDLE1BQU07d0JBQ25DLFNBQVMsRUFBRSxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQVM7d0JBQ3pDLElBQUksRUFBRSxNQUFNO3FCQUNiO2lCQUNGLENBQUM7YUFDSCxDQUFDO1NBQ0gsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUExSEgsa0VBMkhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHVyYXRpb24sIFJlbW92YWxQb2xpY3ksIFRpbWVab25lIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0ICogYXMgbG9ncyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQgKiBhcyBzY2hlZHVsZXIgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNjaGVkdWxlcic7XG5pbXBvcnQgKiBhcyB0YXJnZXRzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zY2hlZHVsZXItdGFyZ2V0cyc7XG5pbXBvcnQgeyBTZWNyZXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc2VjcmV0c21hbmFnZXInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBSdW5uaW5nU2NoZWR1bGVyRnVuY3Rpb24gfSBmcm9tICcuLi9mdW5jcy9ydW5uaW5nLXNjaGVkdWxlci1mdW5jdGlvbic7XG5cbi8qKlxuICogQ3Jvbi1zdHlsZSBzY2hlZHVsZSBjb25maWd1cmF0aW9uIGZvciBzdGFydC9zdG9wIGFjdGlvbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NoZWR1bGUge1xuICAvKiogVGltZSB6b25lIGZvciB0aGUgc2NoZWR1bGUgKGUuZy4gRVRDX1VUQykuICovXG4gIHJlYWRvbmx5IHRpbWV6b25lOiBUaW1lWm9uZTtcbiAgLyoqIENyb24gbWludXRlICgw4oCTNTkpLiAqL1xuICByZWFkb25seSBtaW51dGU/OiBzdHJpbmc7XG4gIC8qKiBDcm9uIGhvdXIgKDDigJMyMykuICovXG4gIHJlYWRvbmx5IGhvdXI/OiBzdHJpbmc7XG4gIC8qKiBDcm9uIGRheSBvZiB3ZWVrIChlLmcuIE1PTi1GUkkpLiAqL1xuICByZWFkb25seSB3ZWVrPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIERlZmluZXMgd2hpY2ggRUMyIGluc3RhbmNlcyBhcmUgdGFyZ2V0ZWQgYnkgdGFnIGtleSBhbmQgdmFsdWVzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRhcmdldFJlc291cmNlIHtcbiAgLyoqIFRhZyBrZXkgdXNlZCB0byBzZWxlY3QgaW5zdGFuY2VzIChlLmcuIFNjaGVkdWxlKS4gKi9cbiAgcmVhZG9ubHkgdGFnS2V5OiBzdHJpbmc7XG4gIC8qKiBUYWcgdmFsdWVzIHRoYXQgbWF0Y2ggaW5zdGFuY2VzIHRvIGluY2x1ZGUuICovXG4gIHJlYWRvbmx5IHRhZ1ZhbHVlczogc3RyaW5nW107XG59XG5cbi8qKlxuICogU2VjcmV0IGlkZW50aWZpZXJzIHJlcXVpcmVkIGJ5IHRoZSBzY2hlZHVsZXIgKGUuZy4gU2xhY2spLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlY3JldHMge1xuICAvKiogTmFtZSBvZiB0aGUgU2VjcmV0cyBNYW5hZ2VyIHNlY3JldCBjb250YWluaW5nIFNsYWNrIHRva2VuIGFuZCBjaGFubmVsLiAqL1xuICByZWFkb25seSBzbGFja1NlY3JldE5hbWU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBjcmVhdGluZyBhbiBFQzIgaW5zdGFuY2UgcnVubmluZyBzY2hlZHVsZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVyUHJvcHMge1xuICAvKiogVGFnLWJhc2VkIHRhcmdldGluZyBmb3IgRUMyIGluc3RhbmNlcyB0byBzdGFydC9zdG9wLiAqL1xuICByZWFkb25seSB0YXJnZXRSZXNvdXJjZTogVGFyZ2V0UmVzb3VyY2U7XG4gIC8qKiBXaGV0aGVyIEV2ZW50QnJpZGdlIFNjaGVkdWxlciBydWxlcyBhcmUgZW5hYmxlZC4gRGVmYXVsdHMgdG8gdHJ1ZSBpZiBvbWl0dGVkLiAqL1xuICByZWFkb25seSBlbmFibGVTY2hlZHVsaW5nPzogYm9vbGVhbjtcbiAgLyoqIFNlY3JldHMgKGUuZy4gU2xhY2spIHVzZWQgZm9yIG5vdGlmaWNhdGlvbnMuICovXG4gIHJlYWRvbmx5IHNlY3JldHM6IFNlY3JldHM7XG4gIC8qKiBDcm9uIHNjaGVkdWxlIGZvciBzdG9wcGluZyBpbnN0YW5jZXMuICovXG4gIHJlYWRvbmx5IHN0b3BTY2hlZHVsZT86IFNjaGVkdWxlO1xuICAvKiogQ3JvbiBzY2hlZHVsZSBmb3Igc3RhcnRpbmcgaW5zdGFuY2VzLiAqL1xuICByZWFkb25seSBzdGFydFNjaGVkdWxlPzogU2NoZWR1bGU7XG59XG5cbi8qKlxuICogUHJvdmlzaW9ucyBFdmVudEJyaWRnZSBTY2hlZHVsZXIgcnVsZXMgYW5kIGEgRHVyYWJsZSBFeGVjdXRpb24gTGFtYmRhIHRoYXQgc3RhcnQvc3RvcCB0YWdnZWQgRUMyIGluc3RhbmNlcy5cbiAqXG4gKiBFYWNoIHNjaGVkdWxlIGludm9rZXMgdGhlIGZ1bmN0aW9uIHdpdGggYFBhcmFtc2AgKGBUYWdLZXlgLCBgVGFnVmFsdWVzYCwgYE1vZGVgKS4gVGhlIGZ1bmN0aW9uIHVzZXNcbiAqIHRoZSBSZXNvdXJjZSBHcm91cHMgVGFnZ2luZyBBUEkgYW5kIEVDMiBBUElzOyBTbGFjayBub3RpZmljYXRpb25zIHVzZSB0aGUgc2VjcmV0IG5hbWVkIGluIHtAbGluayBTZWNyZXRzLnNsYWNrU2VjcmV0TmFtZX0uXG4gKi9cbmV4cG9ydCBjbGFzcyBFQzJJbnN0YW5jZVJ1bm5pbmdTY2hlZHVsZXIgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKipcbiAgICogRGVmaW5lcyBJQU0sIGxvZ2dpbmcsIHR3byBjcm9uIHNjaGVkdWxlcyAoc3RhcnQvc3RvcCksIGFuZCB0aGUgYnVuZGxlZCBydW5uaW5nLXNjaGVkdWxlciBMYW1iZGEgKE5vZGUuanMsIER1cmFibGUgRXhlY3V0aW9uKS5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIC0gUGFyZW50IGNvbnN0cnVjdC5cbiAgICogQHBhcmFtIGlkIC0gQ29uc3RydWN0IGlkLlxuICAgKiBAcGFyYW0gcHJvcHMgLSBUYXJnZXQgdGFncywgb3B0aW9uYWwgY3JvbiBvdmVycmlkZXMsIFNsYWNrIHNlY3JldCBuYW1lLCBhbmQgc2NoZWR1bGUgZW5hYmxlIGZsYWcuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVyUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3Qgc2xhY2tTZWNyZXQgPSBTZWNyZXQuZnJvbVNlY3JldE5hbWVWMih0aGlzLCAnU2xhY2tTZWNyZXQnLCBwcm9wcy5zZWNyZXRzLnNsYWNrU2VjcmV0TmFtZSk7XG5cbiAgICAvLyBEdXJhYmxlIEZ1bmN0aW9ucy1iYXNlZCBSdW5uaW5nIFNjaGVkdWxlciAocHJldmlvdXMgU3RlcCBGdW5jdGlvbnMgbG9naWMgaW1wbGVtZW50ZWQgaW4gTGFtYmRhKS5cbiAgICAvLyBEdXJhYmxlIEV4ZWN1dGlvbiByZXF1aXJlcyBOb2RlLmpzIDIyKy5cbiAgICBjb25zdCBydW5uaW5nU2NoZWR1bGVGdW5jdGlvbiA9IG5ldyBSdW5uaW5nU2NoZWR1bGVyRnVuY3Rpb24odGhpcywgJ1J1bm5pbmdTY2hlZHVsZXJGdW5jdGlvbicsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnU3RhcnRzIGFuZCBzdG9wcyB0YWdnZWQgRUMyIGluc3RhbmNlcyBvbiBFdmVudEJyaWRnZSBTY2hlZHVsZXIgc2NoZWR1bGVzLicsXG4gICAgICBhcmNoaXRlY3R1cmU6IGxhbWJkYS5BcmNoaXRlY3R1cmUuQVJNXzY0LFxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcygxNSksXG4gICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICByZXRyeUF0dGVtcHRzOiAyLFxuICAgICAgZHVyYWJsZUNvbmZpZzoge1xuICAgICAgICBleGVjdXRpb25UaW1lb3V0OiBEdXJhdGlvbi5ob3VycygyKSxcbiAgICAgICAgcmV0ZW50aW9uUGVyaW9kOiBEdXJhdGlvbi5kYXlzKDEpLFxuICAgICAgfSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIFNMQUNLX1NFQ1JFVF9OQU1FOiBwcm9wcy5zZWNyZXRzLnNsYWNrU2VjcmV0TmFtZSxcbiAgICAgIH0sXG4gICAgICBwYXJhbXNBbmRTZWNyZXRzOiBsYW1iZGEuUGFyYW1zQW5kU2VjcmV0c0xheWVyVmVyc2lvbi5mcm9tVmVyc2lvbihsYW1iZGEuUGFyYW1zQW5kU2VjcmV0c1ZlcnNpb25zLlYxXzBfMTAzLCB7XG4gICAgICAgIGNhY2hlU2l6ZTogNTAwLFxuICAgICAgICBsb2dMZXZlbDogbGFtYmRhLlBhcmFtc0FuZFNlY3JldHNMb2dMZXZlbC5JTkZPLFxuICAgICAgfSksXG4gICAgICByb2xlOiBuZXcgaWFtLlJvbGUodGhpcywgJ1J1bm5pbmdTY2hlZHVsZXJGdW5jdGlvblJvbGUnLCB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3dzIHRoZSBydW5uaW5nIHNjaGVkdWxlciB0byBkZXNjcmliZSwgc3RhcnQsIGFuZCBzdG9wIEVDMiBpbnN0YW5jZXMgYW5kIHJlYWQgU2xhY2sgc2VjcmV0cy4nLFxuICAgICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnbGFtYmRhLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgICAgbWFuYWdlZFBvbGljaWVzOiBbXG4gICAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlJyksXG4gICAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNEdXJhYmxlRXhlY3V0aW9uUm9sZVBvbGljeScpLFxuICAgICAgICBdLFxuICAgICAgfSksXG4gICAgICBsb2dHcm91cDogbmV3IGxvZ3MuTG9nR3JvdXAodGhpcywgJ1J1bm5pbmdTY2hlZHVsZXJGdW5jdGlvbkxvZ0dyb3VwJywge1xuICAgICAgICByZXRlbnRpb246IGxvZ3MuUmV0ZW50aW9uRGF5cy5USFJFRV9NT05USFMsXG4gICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIH0pLFxuICAgICAgbG9nZ2luZ0Zvcm1hdDogbGFtYmRhLkxvZ2dpbmdGb3JtYXQuSlNPTixcbiAgICAgIHN5c3RlbUxvZ0xldmVsVjI6IGxhbWJkYS5TeXN0ZW1Mb2dMZXZlbC5JTkZPLFxuICAgICAgYXBwbGljYXRpb25Mb2dMZXZlbFYyOiBsYW1iZGEuQXBwbGljYXRpb25Mb2dMZXZlbC5JTkZPLFxuICAgIH0pO1xuICAgIHJ1bm5pbmdTY2hlZHVsZUZ1bmN0aW9uLmFkZFRvUm9sZVBvbGljeShuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBzaWQ6ICdHZXRSZXNvdXJjZXMnLFxuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9uczogW1xuICAgICAgICAndGFnOkdldFJlc291cmNlcycsXG4gICAgICBdLFxuICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICB9KSk7XG4gICAgLy8gRUMyOiBkZXNjcmliZSBpbnN0YW5jZXMgYW5kIHN0YXJ0L3N0b3AgYnkgaW5zdGFuY2UgaWRcbiAgICBydW5uaW5nU2NoZWR1bGVGdW5jdGlvbi5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgc2lkOiAnRWMyUnVubmluZ0NvbnRyb2wnLFxuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9uczogW1xuICAgICAgICAnZWMyOkRlc2NyaWJlSW5zdGFuY2VzJyxcbiAgICAgICAgJ2VjMjpTdGFydEluc3RhbmNlcycsXG4gICAgICAgICdlYzI6U3RvcEluc3RhbmNlcycsXG4gICAgICBdLFxuICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICB9KSk7XG4gICAgLy8gR3JhbnQgcmVhZCBhY2Nlc3MgdG8gdGhlIFNsYWNrIHNlY3JldFxuICAgIHNsYWNrU2VjcmV0LmdyYW50UmVhZChydW5uaW5nU2NoZWR1bGVGdW5jdGlvbik7XG5cbiAgICAvLyBTZWU6IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9sYW1iZGEvbGF0ZXN0L2RnL2R1cmFibGUtZ2V0dGluZy1zdGFydGVkLWlhYy5odG1sXG4gICAgY29uc3QgcnVubmluZ1NjaGVkdWxlRnVuY3Rpb25BbGlhcyA9IHJ1bm5pbmdTY2hlZHVsZUZ1bmN0aW9uLmFkZEFsaWFzKCdsaXZlJyk7XG5cbiAgICAvLyBXaGV0aGVyIHNjaGVkdWxlcyBhcmUgZW5hYmxlZCAoZGVmYXVsdCB0cnVlIHVubGVzcyBleHBsaWNpdGx5IGRpc2FibGVkKS5cbiAgICBjb25zdCBzY2hlZHVsZUVuYWJsZWQ6IGJvb2xlYW4gPSAoKCkgPT4ge1xuICAgICAgaWYgKHByb3BzLmVuYWJsZVNjaGVkdWxpbmcgPT09IHVuZGVmaW5lZCB8fCBwcm9wcy5lbmFibGVTY2hlZHVsaW5nKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICAvLyBEdXJhYmxlIEZ1bmN0aW9uczogTGFtYmRhIHBlcmZvcm1zIHRhZyBsb29rdXAgYW5kIGluc3RhbmNlIHN0YXJ0L3N0b3AgaW4gYSBzaW5nbGUgcnVuLlxuICAgIG5ldyBzY2hlZHVsZXIuU2NoZWR1bGUodGhpcywgJ1J1bm5pbmdTdGFydFNjaGVkdWxlJywge1xuICAgICAgZGVzY3JpcHRpb246ICdydW5uaW5nIHN0YXJ0IHNjaGVkdWxlJyxcbiAgICAgIGVuYWJsZWQ6IHNjaGVkdWxlRW5hYmxlZCxcbiAgICAgIHNjaGVkdWxlOiBzY2hlZHVsZXIuU2NoZWR1bGVFeHByZXNzaW9uLmNyb24oe1xuICAgICAgICBtaW51dGU6IHByb3BzLnN0YXJ0U2NoZWR1bGU/Lm1pbnV0ZSA/PyAnNTAnLFxuICAgICAgICBob3VyOiBwcm9wcy5zdGFydFNjaGVkdWxlPy5ob3VyID8/ICc3JyxcbiAgICAgICAgd2Vla0RheTogcHJvcHMuc3RhcnRTY2hlZHVsZT8ud2VlayA/PyAnTU9OLUZSSScsXG4gICAgICAgIHRpbWVab25lOiBwcm9wcy5zdGFydFNjaGVkdWxlPy50aW1lem9uZSA/PyBUaW1lWm9uZS5FVENfVVRDLFxuICAgICAgfSksXG4gICAgICB0YXJnZXQ6IG5ldyB0YXJnZXRzLkxhbWJkYUludm9rZShydW5uaW5nU2NoZWR1bGVGdW5jdGlvbkFsaWFzLCB7XG4gICAgICAgIGlucHV0OiBzY2hlZHVsZXIuU2NoZWR1bGVUYXJnZXRJbnB1dC5mcm9tT2JqZWN0KHtcbiAgICAgICAgICBQYXJhbXM6IHtcbiAgICAgICAgICAgIFRhZ0tleTogcHJvcHMudGFyZ2V0UmVzb3VyY2UudGFnS2V5LFxuICAgICAgICAgICAgVGFnVmFsdWVzOiBwcm9wcy50YXJnZXRSZXNvdXJjZS50YWdWYWx1ZXMsXG4gICAgICAgICAgICBNb2RlOiAnU3RhcnQnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgfSksXG4gICAgfSk7XG5cbiAgICBuZXcgc2NoZWR1bGVyLlNjaGVkdWxlKHRoaXMsICdSdW5uaW5nU3RvcFNjaGVkdWxlJywge1xuICAgICAgZGVzY3JpcHRpb246ICdydW5uaW5nIHN0b3Agc2NoZWR1bGUnLFxuICAgICAgZW5hYmxlZDogc2NoZWR1bGVFbmFibGVkLFxuICAgICAgc2NoZWR1bGU6IHNjaGVkdWxlci5TY2hlZHVsZUV4cHJlc3Npb24uY3Jvbih7XG4gICAgICAgIG1pbnV0ZTogcHJvcHMuc3RvcFNjaGVkdWxlPy5taW51dGUgPz8gJzUnLFxuICAgICAgICBob3VyOiBwcm9wcy5zdG9wU2NoZWR1bGU/LmhvdXIgPz8gJzE5JyxcbiAgICAgICAgd2Vla0RheTogcHJvcHMuc3RvcFNjaGVkdWxlPy53ZWVrID8/ICdNT04tRlJJJyxcbiAgICAgICAgdGltZVpvbmU6IHByb3BzLnN0b3BTY2hlZHVsZT8udGltZXpvbmUgPz8gVGltZVpvbmUuRVRDX1VUQyxcbiAgICAgIH0pLFxuICAgICAgdGFyZ2V0OiBuZXcgdGFyZ2V0cy5MYW1iZGFJbnZva2UocnVubmluZ1NjaGVkdWxlRnVuY3Rpb25BbGlhcywge1xuICAgICAgICBpbnB1dDogc2NoZWR1bGVyLlNjaGVkdWxlVGFyZ2V0SW5wdXQuZnJvbU9iamVjdCh7XG4gICAgICAgICAgUGFyYW1zOiB7XG4gICAgICAgICAgICBUYWdLZXk6IHByb3BzLnRhcmdldFJlc291cmNlLnRhZ0tleSxcbiAgICAgICAgICAgIFRhZ1ZhbHVlczogcHJvcHMudGFyZ2V0UmVzb3VyY2UudGFnVmFsdWVzLFxuICAgICAgICAgICAgTW9kZTogJ1N0b3AnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgfSksXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -25,7 +25,7 @@ export interface SchedulerEvent {
|
|
|
25
25
|
* and uses durable `step` / `wait` / `map` so the run can resume across suspensions.
|
|
26
26
|
*
|
|
27
27
|
* @param event - Payload from EventBridge Scheduler; must include `Params.TagKey`, `Params.TagValues`, `Params.Mode`.
|
|
28
|
-
* @param
|
|
28
|
+
* @param ctx - Root durable execution context.
|
|
29
29
|
* @returns
|
|
30
30
|
* - `{ status: 'TargetResourcesNotFound' }` when no instances match the tag filter.
|
|
31
31
|
* - `{ status: 'Completed', processed, results }` when instances were handled (`results` entries match {@link processOneResource}).
|
|
@@ -14,6 +14,7 @@ const client_ec2_1 = require("@aws-sdk/client-ec2");
|
|
|
14
14
|
const client_resource_groups_tagging_api_1 = require("@aws-sdk/client-resource-groups-tagging-api");
|
|
15
15
|
const web_api_1 = require("@slack/web-api");
|
|
16
16
|
const aws_lambda_secret_fetcher_1 = require("aws-lambda-secret-fetcher");
|
|
17
|
+
const safe_env_getter_1 = require("safe-env-getter");
|
|
17
18
|
const running_scheduler_predicates_1 = require("./running-scheduler-predicates");
|
|
18
19
|
/** Mapping of EC2 instance state to display name and emoji for Slack. */
|
|
19
20
|
const STATE_LIST = [
|
|
@@ -50,6 +51,13 @@ const processOneResource = async (ctx, targetResource, params, resourceIndex) =>
|
|
|
50
51
|
const account = arnParts[4] ?? '';
|
|
51
52
|
const region = arnParts[3] ?? '';
|
|
52
53
|
const stepPrefix = `resource-${resourceIndex}-${identifier}`;
|
|
54
|
+
ctx.logger.info('processOneResource: start', {
|
|
55
|
+
resourceIndex,
|
|
56
|
+
identifier,
|
|
57
|
+
region,
|
|
58
|
+
account,
|
|
59
|
+
mode: params.Mode,
|
|
60
|
+
});
|
|
53
61
|
let loopCount = 0;
|
|
54
62
|
let currentState = '';
|
|
55
63
|
do {
|
|
@@ -58,21 +66,37 @@ const processOneResource = async (ctx, targetResource, params, resourceIndex) =>
|
|
|
58
66
|
const out = await ec2.send(new client_ec2_1.DescribeInstancesCommand({ InstanceIds: [identifier] }));
|
|
59
67
|
return out.Reservations?.[0]?.Instances?.[0]?.State?.Name ?? 'unknown';
|
|
60
68
|
});
|
|
69
|
+
ctx.logger.info('processOneResource: described', {
|
|
70
|
+
identifier,
|
|
71
|
+
loopCount,
|
|
72
|
+
currentState,
|
|
73
|
+
mode: params.Mode,
|
|
74
|
+
});
|
|
61
75
|
const mode = params.Mode;
|
|
62
76
|
if (mode === 'Start' && currentState === 'stopped') {
|
|
77
|
+
ctx.logger.info('processOneResource: starting instance', { identifier, loopCount });
|
|
63
78
|
await ctx.step(`${stepPrefix}-start-${loopCount}`, async () => {
|
|
64
79
|
const ec2 = new client_ec2_1.EC2Client({});
|
|
65
80
|
await ec2.send(new client_ec2_1.StartInstancesCommand({ InstanceIds: [identifier] }));
|
|
66
81
|
});
|
|
82
|
+
ctx.logger.info('processOneResource: wait after start', {
|
|
83
|
+
identifier,
|
|
84
|
+
seconds: STATUS_CHANGE_WAIT_SECONDS,
|
|
85
|
+
});
|
|
67
86
|
await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
|
|
68
87
|
loopCount += 1;
|
|
69
88
|
continue;
|
|
70
89
|
}
|
|
71
90
|
if (mode === 'Stop' && currentState === 'running') {
|
|
91
|
+
ctx.logger.info('processOneResource: stopping instance', { identifier, loopCount });
|
|
72
92
|
await ctx.step(`${stepPrefix}-stop-${loopCount}`, async () => {
|
|
73
93
|
const ec2 = new client_ec2_1.EC2Client({});
|
|
74
94
|
await ec2.send(new client_ec2_1.StopInstancesCommand({ InstanceIds: [identifier] }));
|
|
75
95
|
});
|
|
96
|
+
ctx.logger.info('processOneResource: wait after stop', {
|
|
97
|
+
identifier,
|
|
98
|
+
seconds: STATUS_CHANGE_WAIT_SECONDS,
|
|
99
|
+
});
|
|
76
100
|
await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
|
|
77
101
|
loopCount += 1;
|
|
78
102
|
continue;
|
|
@@ -81,13 +105,32 @@ const processOneResource = async (ctx, targetResource, params, resourceIndex) =>
|
|
|
81
105
|
const transitioning = (mode === 'Start' && currentState === 'pending') ||
|
|
82
106
|
(mode === 'Stop' && (currentState === 'stopping' || currentState === 'shutting-down'));
|
|
83
107
|
if (transitioning) {
|
|
108
|
+
ctx.logger.info('processOneResource: wait while transitioning', {
|
|
109
|
+
identifier,
|
|
110
|
+
loopCount,
|
|
111
|
+
currentState,
|
|
112
|
+
mode,
|
|
113
|
+
seconds: STATUS_CHANGE_WAIT_SECONDS,
|
|
114
|
+
});
|
|
84
115
|
await ctx.wait({ seconds: STATUS_CHANGE_WAIT_SECONDS });
|
|
85
116
|
loopCount += 1;
|
|
86
117
|
continue;
|
|
87
118
|
}
|
|
119
|
+
ctx.logger.error('processOneResource: unexpected state', {
|
|
120
|
+
identifier,
|
|
121
|
+
mode,
|
|
122
|
+
currentState,
|
|
123
|
+
loopCount,
|
|
124
|
+
});
|
|
88
125
|
throw new Error(`instance status fail: mode=${mode} currentState=${currentState}`);
|
|
89
126
|
}
|
|
90
127
|
} while (!(0, running_scheduler_predicates_1.isDesiredStableState)(params.Mode, currentState));
|
|
128
|
+
ctx.logger.info('processOneResource: reached desired stable state', {
|
|
129
|
+
identifier,
|
|
130
|
+
finalState: currentState,
|
|
131
|
+
mode: params.Mode,
|
|
132
|
+
loopCount,
|
|
133
|
+
});
|
|
91
134
|
return {
|
|
92
135
|
identifier,
|
|
93
136
|
account,
|
|
@@ -104,60 +147,83 @@ const processOneResource = async (ctx, targetResource, params, resourceIndex) =>
|
|
|
104
147
|
* and uses durable `step` / `wait` / `map` so the run can resume across suspensions.
|
|
105
148
|
*
|
|
106
149
|
* @param event - Payload from EventBridge Scheduler; must include `Params.TagKey`, `Params.TagValues`, `Params.Mode`.
|
|
107
|
-
* @param
|
|
150
|
+
* @param ctx - Root durable execution context.
|
|
108
151
|
* @returns
|
|
109
152
|
* - `{ status: 'TargetResourcesNotFound' }` when no instances match the tag filter.
|
|
110
153
|
* - `{ status: 'Completed', processed, results }` when instances were handled (`results` entries match {@link processOneResource}).
|
|
111
154
|
* @throws {Error} If `Params` is invalid, `SLACK_SECRET_NAME` is unset, the Slack secret is incomplete, or instance processing fails.
|
|
112
155
|
*/
|
|
113
|
-
exports.handler = (0, durable_execution_sdk_js_1.withDurableExecution)(async (event,
|
|
156
|
+
exports.handler = (0, durable_execution_sdk_js_1.withDurableExecution)(async (event, ctx) => {
|
|
114
157
|
const params = event.Params;
|
|
158
|
+
ctx.logger.info('running-scheduler: invocation', {
|
|
159
|
+
mode: params?.Mode,
|
|
160
|
+
tagKey: params?.TagKey,
|
|
161
|
+
tagValueCount: params?.TagValues?.length ?? 0,
|
|
162
|
+
});
|
|
115
163
|
if (!params?.TagKey || !params?.TagValues || !params?.Mode) {
|
|
116
164
|
throw new Error('Invalid event: Params.TagKey, Params.TagValues, Params.Mode are required.');
|
|
117
165
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const slackSecretValue = await context.step('fetch-slack-secret', async () => {
|
|
166
|
+
// safe get Secrets name from environment variable
|
|
167
|
+
const slackSecretName = safe_env_getter_1.SafeEnvGetter.getEnv('SLACK_SECRET_NAME');
|
|
168
|
+
const slackSecretValue = await ctx.step('fetch-slack-secret', async () => {
|
|
169
|
+
ctx.logger.info('running-scheduler: fetching Slack secret', { secretName: slackSecretName });
|
|
123
170
|
return aws_lambda_secret_fetcher_1.secretFetcher.getSecretValue(slackSecretName);
|
|
124
171
|
});
|
|
172
|
+
ctx.logger.info('running-scheduler: Slack secret loaded');
|
|
125
173
|
if (!slackSecretValue?.token || !slackSecretValue?.channel) {
|
|
126
174
|
throw new Error('Slack secret must contain token and channel.');
|
|
127
175
|
}
|
|
128
|
-
const targetResources = await
|
|
176
|
+
const targetResources = await ctx.step('get-target-resources', async () => {
|
|
129
177
|
const client = new client_resource_groups_tagging_api_1.ResourceGroupsTaggingAPIClient({});
|
|
130
178
|
const result = await client.send(new client_resource_groups_tagging_api_1.GetResourcesCommand({
|
|
131
179
|
ResourceTypeFilters: ['ec2:instance'],
|
|
132
180
|
TagFilters: [{ Key: params.TagKey, Values: params.TagValues }],
|
|
133
181
|
}));
|
|
134
|
-
|
|
182
|
+
const arns = (result.ResourceTagMappingList ?? [])
|
|
135
183
|
.map((m) => m.ResourceARN)
|
|
136
184
|
.filter((arn) => arn != null);
|
|
185
|
+
ctx.logger.info('running-scheduler: get-target-resources done', { count: arns.length });
|
|
186
|
+
return arns;
|
|
137
187
|
});
|
|
138
188
|
if (targetResources.length === 0) {
|
|
189
|
+
ctx.logger.info('running-scheduler: no matching instances', { tagKey: params.TagKey });
|
|
139
190
|
return { status: 'TargetResourcesNotFound' };
|
|
140
191
|
}
|
|
141
192
|
const client = new web_api_1.WebClient(slackSecretValue.token);
|
|
142
193
|
const channel = slackSecretValue.channel;
|
|
194
|
+
ctx.logger.info('running-scheduler: posting parent Slack message', {
|
|
195
|
+
instanceCount: targetResources.length,
|
|
196
|
+
});
|
|
143
197
|
// send slack message
|
|
144
|
-
const slackParentMessageResult = await
|
|
198
|
+
const slackParentMessageResult = await ctx.step('post-slack-messages', async () => {
|
|
145
199
|
return client.chat.postMessage({
|
|
146
200
|
channel,
|
|
147
201
|
text: `${params.Mode === 'Start' ? '😆 Starts' : '🥱 Stops'} the scheduled EC2 Instance.`,
|
|
148
202
|
});
|
|
149
203
|
});
|
|
150
|
-
|
|
204
|
+
ctx.logger.info('running-scheduler: parent Slack message posted', {
|
|
205
|
+
threadTs: slackParentMessageResult?.ts ?? null,
|
|
206
|
+
});
|
|
207
|
+
ctx.logger.info('running-scheduler: starting parallel instance processing', {
|
|
208
|
+
count: targetResources.length,
|
|
209
|
+
maxConcurrency: 10,
|
|
210
|
+
});
|
|
211
|
+
const results = await ctx.map(targetResources,
|
|
151
212
|
// async (ctx: DurableContext, targetResource: string, index: number) =>
|
|
152
213
|
// ctx.step(`process-resource-${index}`, async () =>
|
|
153
214
|
// processOneResource(ctx, targetResource, params, index),
|
|
154
215
|
// ),
|
|
155
|
-
async (
|
|
156
|
-
return
|
|
216
|
+
async (mapCtx, targetResource, index) => {
|
|
217
|
+
return mapCtx.runInChildContext(`resource-${index}`, async (childCtx) => {
|
|
157
218
|
const result = await processOneResource(childCtx, targetResource, params, index);
|
|
158
219
|
// if (result.status === 'skipped') {
|
|
159
220
|
// return result;
|
|
160
221
|
// }
|
|
222
|
+
childCtx.logger.info('running-scheduler: posting thread Slack message', {
|
|
223
|
+
index,
|
|
224
|
+
identifier: result.identifier,
|
|
225
|
+
status: result.status,
|
|
226
|
+
});
|
|
161
227
|
// send slack thread message
|
|
162
228
|
await childCtx.step('post-slack-child-messages', async () => {
|
|
163
229
|
const display = getStateDisplay(result.status);
|
|
@@ -182,10 +248,14 @@ exports.handler = (0, durable_execution_sdk_js_1.withDurableExecution)(async (ev
|
|
|
182
248
|
});
|
|
183
249
|
}, { maxConcurrency: 10 });
|
|
184
250
|
const resultList = Array.isArray(results) ? results : [];
|
|
251
|
+
ctx.logger.info('running-scheduler: completed', {
|
|
252
|
+
processed: targetResources.length,
|
|
253
|
+
resultCount: resultList.length,
|
|
254
|
+
});
|
|
185
255
|
return {
|
|
186
256
|
status: 'Completed',
|
|
187
257
|
processed: targetResources.length,
|
|
188
258
|
results: resultList,
|
|
189
259
|
};
|
|
190
260
|
});
|
|
191
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVubmluZy1zY2hlZHVsZXIubGFtYmRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Z1bmNzL3J1bm5pbmctc2NoZWR1bGVyLmxhbWJkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7R0FPRzs7O0FBRUgsNEVBQTBGO0FBQzFGLG9EQUs2QjtBQUM3QixvR0FBa0g7QUFDbEgsNENBQTJDO0FBQzNDLHlFQUEwRDtBQUMxRCxpRkFBc0U7QUFFdEUseUVBQXlFO0FBQ3pFLE1BQU0sVUFBVSxHQUFHO0lBQ2pCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7SUFDbEQsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRTtDQUMxQyxDQUFDO0FBRVgsdUVBQXVFO0FBQ3ZFLE1BQU0sMEJBQTBCLEdBQUcsRUFBRSxDQUFDO0FBc0J0Qzs7Ozs7R0FLRztBQUNILE1BQU0sZUFBZSxHQUFHLENBQUMsT0FBZSxFQUErQyxFQUFFO0lBQ3ZGLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDLENBQUM7SUFDMUQsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3RFLENBQUMsQ0FBQztBQUVGOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLGtCQUFrQixHQUFHLEtBQUssRUFDOUIsR0FBbUIsRUFDbkIsY0FBc0IsRUFDdEIsTUFBZ0MsRUFDaEMsYUFBcUIsRUFDK0UsRUFBRTtJQUN0RyxNQUFNLEtBQUssR0FBRyxjQUFj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LyoqXG4gKiBFQzIgUnVubmluZyBTY2hlZHVsZXIg4oCTIER1cmFibGUgRnVuY3Rpb25zIGltcGxlbWVudGF0aW9uLlxuICpcbiAqIEltcGxlbWVudHMgdGhlIHJ1bm5pbmctY29udHJvbCBmbG93IHVzaW5nIEFXUyBMYW1iZGEgRHVyYWJsZSBFeGVjdXRpb24uXG4gKiBTdGVwIGNoZWNrcG9pbnRzLCB3YWl0IChubyBjaGFyZ2UpLCBhbmQgcGFyYWxsZWwgbWFwIHByb3ZpZGUgYSBmbG93IGVxdWl2YWxlbnQgdG8gU3RlcCBGdW5jdGlvbnMuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9kdXJhYmxlLWV4ZWN1dGlvbi1zZGsuaHRtbFxuICovXG5cbmltcG9ydCB7IHdpdGhEdXJhYmxlRXhlY3V0aW9uLCB0eXBlIER1cmFibGVDb250ZXh0IH0gZnJvbSAnQGF3cy9kdXJhYmxlLWV4ZWN1dGlvbi1zZGstanMnO1xuaW1wb3J0IHtcbiAgRUMyQ2xpZW50LFxuICBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmQsXG4gIFN0YXJ0SW5zdGFuY2VzQ29tbWFuZCxcbiAgU3RvcEluc3RhbmNlc0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1lYzInO1xuaW1wb3J0IHsgR2V0UmVzb3VyY2VzQ29tbWFuZCwgUmVzb3VyY2VHcm91cHNUYWdnaW5nQVBJQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXJlc291cmNlLWdyb3Vwcy10YWdnaW5nLWFwaSc7XG5pbXBvcnQgeyBXZWJDbGllbnQgfSBmcm9tICdAc2xhY2svd2ViLWFwaSc7XG5pbXBvcnQgeyBzZWNyZXRGZXRjaGVyIH0gZnJvbSAnYXdzLWxhbWJkYS1zZWNyZXQtZmV0Y2hlcic7XG5pbXBvcnQgeyBpc0Rlc2lyZWRTdGFibGVTdGF0ZSB9IGZyb20gJy4vcnVubmluZy1zY2hlZHVsZXItcHJlZGljYXRlcyc7XG5cbi8qKiBNYXBwaW5nIG9mIEVDMiBpbnN0YW5jZSBzdGF0ZSB0byBkaXNwbGF5IG5hbWUgYW5kIGVtb2ppIGZvciBTbGFjay4gKi9cbmNvbnN0IFNUQVRFX0xJU1QgPSBbXG4gIHsgbmFtZTogJ1JVTk5JTkcnLCBlbW9qaTogJ/CfmIYnLCBzdGF0ZTogJ3J1bm5pbmcnIH0sXG4gIHsgbmFtZTogJ1NUT1BQRUQnLCBlbW9qaTogJ/CfmLQnLCBzdGF0ZTogJ3N0b3BwZWQnIH0sXG5dIGFzIGNvbnN0O1xuXG4vKiogU2Vjb25kcyB0byB3YWl0IGJldHdlZW4gcG9sbGluZyBpbnN0YW5jZSBzdGF0ZSBhZnRlciBzdGFydC9zdG9wLiAqL1xuY29uc3QgU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMgPSAyMDtcblxuLyoqIEV2ZW50IHBheWxvYWQgZnJvbSBFdmVudEJyaWRnZSBTY2hlZHVsZXIgaW52b2tpbmcgdGhpcyBMYW1iZGEuICovXG5leHBvcnQgaW50ZXJmYWNlIFNjaGVkdWxlckV2ZW50IHtcbiAgUGFyYW1zOiB7XG4gICAgLyoqIFRhZyBrZXkgdXNlZCB0byBzZWxlY3QgRUMyIGluc3RhbmNlcy4gKi9cbiAgICBUYWdLZXk6IHN0cmluZztcbiAgICAvKiogVGFnIHZhbHVlcyB0byBtYXRjaC4gKi9cbiAgICBUYWdWYWx1ZXM6IHN0cmluZ1tdO1xuICAgIC8qKiBXaGV0aGVyIHRvIHN0YXJ0IG9yIHN0b3AgaW5zdGFuY2VzLiAqL1xuICAgIE1vZGU6ICdTdGFydCcgfCAnU3RvcCc7XG4gIH07XG59XG5cbi8qKiBTbGFjayBjcmVkZW50aWFscyBhbmQgZGVmYXVsdCBjaGFubmVsIGxvYWRlZCBmcm9tIFNlY3JldHMgTWFuYWdlciAoYFNMQUNLX1NFQ1JFVF9OQU1FYCkuICovXG5pbnRlcmZhY2UgU2xhY2tTZWNyZXQge1xuICAvKiogU2xhY2sgYm90IHRva2VuIGZvciB0aGUgU2xhY2sgYFdlYkNsaWVudGAuICovXG4gIHRva2VuOiBzdHJpbmc7XG4gIC8qKiBDaGFubmVsIElEIG9yIG5hbWUgcGFzc2VkIHRvIGBjaGF0LnBvc3RNZXNzYWdlYC4gKi9cbiAgY2hhbm5lbDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJldHVybnMgZGlzcGxheSBuYW1lIGFuZCBlbW9qaSBmb3IgYW4gRUMyIGluc3RhbmNlIHN0YXRlLlxuICpcbiAqIEBwYXJhbSBjdXJyZW50IC0gQ3VycmVudCBpbnN0YW5jZSBzdGF0ZSAoZS5nLiAncnVubmluZycsICdzdG9wcGVkJykuXG4gKiBAcmV0dXJucyBEaXNwbGF5IGluZm8gb3IgdW5kZWZpbmVkIGlmIHN0YXRlIGlzIG5vdCBpbiBTVEFURV9MSVNULlxuICovXG5jb25zdCBnZXRTdGF0ZURpc3BsYXkgPSAoY3VycmVudDogc3RyaW5nKTogeyBlbW9qaTogc3RyaW5nOyBuYW1lOiBzdHJpbmcgfSB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IGZvdW5kID0gU1RBVEVfTElTVC5maW5kKChzKSA9PiBzLnN0YXRlID09PSBjdXJyZW50KTtcbiAgcmV0dXJuIGZvdW5kID8geyBlbW9qaTogZm91bmQuZW1vamksIG5hbWU6IGZvdW5kLm5hbWUgfSA6IHVuZGVmaW5lZDtcbn07XG5cbi8qKlxuICogUHJvY2Vzc2VzIG9uZSBFQzIgaW5zdGFuY2U6IGRlc2NyaWJlcyBzdGF0ZSwgaXNzdWVzIHN0YXJ0L3N0b3Agd2hlbiBuZWVkZWQsIHRoZW4gcG9sbHMgdW50aWxcbiAqIHtAbGluayBpc0Rlc2lyZWRTdGFibGVTdGF0ZX0gaXMgc2F0aXNmaWVkIChkdXJhYmxlIGBzdGVwYCAvIGB3YWl0YCBiZXR3ZWVuIGF0dGVtcHRzKS5cbiAqXG4gKiBAcGFyYW0gY3R4IC0gRHVyYWJsZSBleGVjdXRpb24gY29udGV4dCAoY2hpbGQgY29udGV4dCBwZXIgaW5zdGFuY2UgcmVjb21tZW5kZWQpLlxuICogQHBhcmFtIHRhcmdldFJlc291cmNlIC0gRUMyIGluc3RhbmNlIEFSTi5cbiAqIEBwYXJhbSBwYXJhbXMgLSBTY2hlZHVsZXIgcGFyYW1zIChgVGFnS2V5YCwgYFRhZ1ZhbHVlc2AsIGBNb2RlYCkuXG4gKiBAcGFyYW0gcmVzb3VyY2VJbmRleCAtIEluZGV4IHVzZWQgaW4gZHVyYWJsZSBzdGVwIG5hbWVzIGZvciB0aGlzIHJlc291cmNlLlxuICogQHJldHVybnMgRmluYWwgcmVzb3VyY2UgQVJOLCBFQzIgc3RhdGUgbmFtZSwgcGFyc2VkIGFjY291bnQsIHJlZ2lvbiwgYW5kIGluc3RhbmNlIGlkLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBzdGF0ZSBpcyBuZWl0aGVyIGFjdGlvbmFibGUsIHRyYW5zaXRpb25pbmcsIG5vciB0aGUgZGVzaXJlZCBzdGFibGUgc3RhdGUuXG4gKi9cbmNvbnN0IHByb2Nlc3NPbmVSZXNvdXJjZSA9IGFzeW5jIChcbiAgY3R4OiBEdXJhYmxlQ29udGV4dCxcbiAgdGFyZ2V0UmVzb3VyY2U6IHN0cmluZyxcbiAgcGFyYW1zOiBTY2hlZHVsZXJFdmVudFsnUGFyYW1zJ10sXG4gIHJlc291cmNlSW5kZXg6IG51bWJlcixcbik6IFByb21pc2U8eyByZXNvdXJjZTogc3RyaW5nOyBzdGF0dXM6IHN0cmluZzsgYWNjb3VudDogc3RyaW5nOyByZWdpb246IHN0cmluZzsgaWRlbnRpZmllcjogc3RyaW5nIH0+ID0+IHtcbiAgY29uc3QgcGFydHMgPSB0YXJnZXRSZXNvdXJjZS5zcGxpdCgnLycpO1xuICBjb25zdCBpZGVudGlmaWVyID0gcGFydHNbcGFydHMubGVuZ3RoIC0gMV0gPz8gJ3Vua25vd24nO1xuICBjb25zdCBhcm5QYXJ0cyA9IHRhcmdldFJlc291cmNlLnNwbGl0KCc6Jyk7XG4gIGNvbnN0IGFjY291bnQgPSBhcm5QYXJ0c1s0XSA/PyAnJztcbiAgY29uc3QgcmVnaW9uID0gYXJuUGFydHNbM10gPz8gJyc7XG4gIGNvbnN0IHN0ZXBQcmVmaXggPSBgcmVzb3VyY2UtJHtyZXNvdXJjZUluZGV4fS0ke2lkZW50aWZpZXJ9YDtcblxuICBsZXQgbG9vcENvdW50ID0gMDtcbiAgbGV0IGN1cnJlbnRTdGF0ZSA9ICcnO1xuICBkbyB7XG4gICAgY3VycmVudFN0YXRlID0gYXdhaXQgY3R4LnN0ZXAoYCR7c3RlcFByZWZpeH0tZGVzY3JpYmUtJHtsb29wQ291bnR9YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZWMyID0gbmV3IEVDMkNsaWVudCh7fSk7XG4gICAgICBjb25zdCBvdXQgPSBhd2FpdCBlYzIuc2VuZChuZXcgRGVzY3JpYmVJbnN0YW5jZXNDb21tYW5kKHsgSW5zdGFuY2VJZHM6IFtpZGVudGlmaWVyXSB9KSk7XG4gICAgICByZXR1cm4gb3V0LlJlc2VydmF0aW9ucz8uWzBdPy5JbnN0YW5jZXM/LlswXT8uU3RhdGU/Lk5hbWUgPz8gJ3Vua25vd24nO1xuICAgIH0pO1xuXG4gICAgY29uc3QgbW9kZSA9IHBhcmFtcy5Nb2RlO1xuXG4gICAgaWYgKG1vZGUgPT09ICdTdGFydCcgJiYgY3VycmVudFN0YXRlID09PSAnc3RvcHBlZCcpIHtcbiAgICAgIGF3YWl0IGN0eC5zdGVwKGAke3N0ZXBQcmVmaXh9LXN0YXJ0LSR7bG9vcENvdW50fWAsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgZWMyID0gbmV3IEVDMkNsaWVudCh7fSk7XG4gICAgICAgIGF3YWl0IGVjMi5zZW5kKG5ldyBTdGFydEluc3RhbmNlc0NvbW1hbmQoeyBJbnN0YW5jZUlkczogW2lkZW50aWZpZXJdIH0pKTtcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgY3R4LndhaXQoeyBzZWNvbmRzOiBTVEFUVVNfQ0hBTkdFX1dBSVRfU0VDT05EUyB9KTtcbiAgICAgIGxvb3BDb3VudCArPSAxO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKG1vZGUgPT09ICdTdG9wJyAmJiBjdXJyZW50U3RhdGUgPT09ICdydW5uaW5nJykge1xuICAgICAgYXdhaXQgY3R4LnN0ZXAoYCR7c3RlcFByZWZpeH0tc3RvcC0ke2xvb3BDb3VudH1gLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGVjMiA9IG5ldyBFQzJDbGllbnQoe30pO1xuICAgICAgICBhd2FpdCBlYzIuc2VuZChuZXcgU3RvcEluc3RhbmNlc0NvbW1hbmQoeyBJbnN0YW5jZUlkczogW2lkZW50aWZpZXJdIH0pKTtcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgY3R4LndhaXQoeyBzZWNvbmRzOiBTVEFUVVNfQ0hBTkdFX1dBSVRfU0VDT05EUyB9KTtcbiAgICAgIGxvb3BDb3VudCArPSAxO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKCFpc0Rlc2lyZWRTdGFibGVTdGF0ZShtb2RlLCBjdXJyZW50U3RhdGUpKSB7XG4gICAgICBjb25zdCB0cmFuc2l0aW9uaW5nID1cbiAgICAgICAgKG1vZGUgPT09ICdTdGFydCcgJiYgY3VycmVudFN0YXRlID09PSAncGVuZGluZycpIHx8XG4gICAgICAgIChtb2RlID09PSAnU3RvcCcgJiYgKGN1cnJlbnRTdGF0ZSA9PT0gJ3N0b3BwaW5nJyB8fCBjdXJyZW50U3RhdGUgPT09ICdzaHV0dGluZy1kb3duJykpO1xuXG4gICAgICBpZiAodHJhbnNpdGlvbmluZykge1xuICAgICAgICBhd2FpdCBjdHgud2FpdCh7IHNlY29uZHM6IFNUQVRVU19DSEFOR0VfV0FJVF9TRUNPTkRTIH0pO1xuICAgICAgICBsb29wQ291bnQgKz0gMTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW5zdGFuY2Ugc3RhdHVzIGZhaWw6IG1vZGU9JHttb2RlfSBjdXJyZW50U3RhdGU9JHtjdXJyZW50U3RhdGV9YCk7XG4gICAgfVxuICB9IHdoaWxlICghaXNEZXNpcmVkU3RhYmxlU3RhdGUocGFyYW1zLk1vZGUsIGN1cnJlbnRTdGF0ZSkpO1xuXG4gIHJldHVybiB7XG4gICAgaWRlbnRpZmllcixcbiAgICBhY2NvdW50LFxuICAgIHJlZ2lvbixcbiAgICByZXNvdXJjZTogdGFyZ2V0UmVzb3VyY2UsXG4gICAgc3RhdHVzOiBjdXJyZW50U3RhdGUsXG4gIH07XG59O1xuXG4vKipcbiAqIER1cmFibGUgTGFtYmRhIGVudHJ5IHBvaW50IGZvciB0aGUgRUMyIHJ1bm5pbmcgc2NoZWR1bGVyLlxuICpcbiAqIFJlc29sdmVzIGluc3RhbmNlcyB2aWEgUmVzb3VyY2UgR3JvdXBzIFRhZ2dpbmcgQVBJLCBydW5zIHtAbGluayBwcm9jZXNzT25lUmVzb3VyY2V9IGZvciBlYWNoIEFSTlxuICogaW4gcGFyYWxsZWwgKGJvdW5kZWQgY29uY3VycmVuY3kpLCBwb3N0cyBhIHBhcmVudCBTbGFjayBtZXNzYWdlIGFuZCBwZXItaW5zdGFuY2UgdGhyZWFkIHJlcGxpZXMsXG4gKiBhbmQgdXNlcyBkdXJhYmxlIGBzdGVwYCAvIGB3YWl0YCAvIGBtYXBgIHNvIHRoZSBydW4gY2FuIHJlc3VtZSBhY3Jvc3Mgc3VzcGVuc2lvbnMuXG4gKlxuICogQHBhcmFtIGV2ZW50IC0gUGF5bG9hZCBmcm9tIEV2ZW50QnJpZGdlIFNjaGVkdWxlcjsgbXVzdCBpbmNsdWRlIGBQYXJhbXMuVGFnS2V5YCwgYFBhcmFtcy5UYWdWYWx1ZXNgLCBgUGFyYW1zLk1vZGVgLlxuICogQHBhcmFtIGNvbnRleHQgLSBSb290IGR1cmFibGUgZXhlY3V0aW9uIGNvbnRleHQuXG4gKiBAcmV0dXJuc1xuICogLSBgeyBzdGF0dXM6ICdUYXJnZXRSZXNvdXJjZXNOb3RGb3VuZCcgfWAgd2hlbiBubyBpbnN0YW5jZXMgbWF0Y2ggdGhlIHRhZyBmaWx0ZXIuXG4gKiAtIGB7IHN0YXR1czogJ0NvbXBsZXRlZCcsIHByb2Nlc3NlZCwgcmVzdWx0cyB9YCB3aGVuIGluc3RhbmNlcyB3ZXJlIGhhbmRsZWQgKGByZXN1bHRzYCBlbnRyaWVzIG1hdGNoIHtAbGluayBwcm9jZXNzT25lUmVzb3VyY2V9KS5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBgUGFyYW1zYCBpcyBpbnZhbGlkLCBgU0xBQ0tfU0VDUkVUX05BTUVgIGlzIHVuc2V0LCB0aGUgU2xhY2sgc2VjcmV0IGlzIGluY29tcGxldGUsIG9yIGluc3RhbmNlIHByb2Nlc3NpbmcgZmFpbHMuXG4gKi9cbmV4cG9ydCBjb25zdCBoYW5kbGVyID0gd2l0aER1cmFibGVFeGVjdXRpb24oYXN5bmMgKGV2ZW50OiBTY2hlZHVsZXJFdmVudCwgY29udGV4dDogRHVyYWJsZUNvbnRleHQpID0+IHtcblxuICBjb25zdCBwYXJhbXMgPSBldmVudC5QYXJhbXM7XG5cbiAgaWYgKCFwYXJhbXM/LlRhZ0tleSB8fCAhcGFyYW1zPy5UYWdWYWx1ZXMgfHwgIXBhcmFtcz8uTW9kZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBldmVudDogUGFyYW1zLlRhZ0tleSwgUGFyYW1zLlRhZ1ZhbHVlcywgUGFyYW1zLk1vZGUgYXJlIHJlcXVpcmVkLicpO1xuICB9XG4gIGNvbnN0IHNsYWNrU2VjcmV0TmFtZSA9IHByb2Nlc3MuZW52LlNMQUNLX1NFQ1JFVF9OQU1FO1xuICBpZiAoIXNsYWNrU2VjcmV0TmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBlbnZpcm9ubWVudCB2YXJpYWJsZSBTTEFDS19TRUNSRVRfTkFNRS4nKTtcbiAgfVxuICBjb25zdCBzbGFja1NlY3JldFZhbHVlID0gYXdhaXQgY29udGV4dC5zdGVwKCdmZXRjaC1zbGFjay1zZWNyZXQnLCBhc3luYyAoKSA9PiB7XG4gICAgcmV0dXJuIHNlY3JldEZldGNoZXIuZ2V0U2VjcmV0VmFsdWU8U2xhY2tTZWNyZXQ+KHNsYWNrU2VjcmV0TmFtZSk7XG4gIH0pO1xuXG4gIGlmICghc2xhY2tTZWNyZXRWYWx1ZT8udG9rZW4gfHwgIXNsYWNrU2VjcmV0VmFsdWU/LmNoYW5uZWwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1NsYWNrIHNlY3JldCBtdXN0IGNvbnRhaW4gdG9rZW4gYW5kIGNoYW5uZWwuJyk7XG4gIH1cblxuICBjb25zdCB0YXJnZXRSZXNvdXJjZXMgPSBhd2FpdCBjb250ZXh0LnN0ZXAoJ2dldC10YXJnZXQtcmVzb3VyY2VzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBSZXNvdXJjZUdyb3Vwc1RhZ2dpbmdBUElDbGllbnQoe30pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5zZW5kKFxuICAgICAgbmV3IEdldFJlc291cmNlc0NvbW1hbmQoe1xuICAgICAgICBSZXNvdXJjZVR5cGVGaWx0ZXJzOiBbJ2VjMjppbnN0YW5jZSddLFxuICAgICAgICBUYWdGaWx0ZXJzOiBbeyBLZXk6IHBhcmFtcy5UYWdLZXksIFZhbHVlczogcGFyYW1zLlRhZ1ZhbHVlcyB9XSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgcmV0dXJuIChyZXN1bHQuUmVzb3VyY2VUYWdNYXBwaW5nTGlzdCA/PyBbXSlcbiAgICAgIC5tYXAoKG06IHsgUmVzb3VyY2VBUk4/OiBzdHJpbmcgfSkgPT4gbS5SZXNvdXJjZUFSTilcbiAgICAgIC5maWx0ZXIoKGFybjogc3RyaW5nIHwgdW5kZWZpbmVkKTogYXJuIGlzIHN0cmluZyA9PiBhcm4gIT0gbnVsbCk7XG4gIH0pO1xuXG4gIGlmICh0YXJnZXRSZXNvdXJjZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHsgc3RhdHVzOiAnVGFyZ2V0UmVzb3VyY2VzTm90Rm91bmQnIGFzIGNvbnN0IH07XG4gIH1cblxuICBjb25zdCBjbGllbnQgPSBuZXcgV2ViQ2xpZW50KHNsYWNrU2VjcmV0VmFsdWUudG9rZW4pO1xuICBjb25zdCBjaGFubmVsID0gc2xhY2tTZWNyZXRWYWx1ZS5jaGFubmVsO1xuXG4gIC8vIHNlbmQgc2xhY2sgbWVzc2FnZVxuICBjb25zdCBzbGFja1BhcmVudE1lc3NhZ2VSZXN1bHQgPSBhd2FpdCBjb250ZXh0LnN0ZXAoJ3Bvc3Qtc2xhY2stbWVzc2FnZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgcmV0dXJuIGNsaWVudC5jaGF0LnBvc3RNZXNzYWdlKHtcbiAgICAgIGNoYW5uZWwsXG4gICAgICB0ZXh0OiBgJHtwYXJhbXMuTW9kZSA9PT0gJ1N0YXJ0JyA/ICfwn5iGIFN0YXJ0cycgOiAn8J+lsSBTdG9wcyd9IHRoZSBzY2hlZHVsZWQgRUMyIEluc3RhbmNlLmAsXG4gICAgfSk7XG4gIH0pO1xuXG4gIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBjb250ZXh0Lm1hcChcbiAgICB0YXJnZXRSZXNvdXJjZXMsXG4gICAgLy8gYXN5bmMgKGN0eDogRHVyYWJsZUNvbnRleHQsIHRhcmdldFJlc291cmNlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+XG4gICAgLy8gICBjdHguc3RlcChgcHJvY2Vzcy1yZXNvdXJjZS0ke2luZGV4fWAsIGFzeW5jICgpID0+XG4gICAgLy8gICAgIHByb2Nlc3NPbmVSZXNvdXJjZShjdHgsIHRhcmdldFJlc291cmNlLCBwYXJhbXMsIGluZGV4KSxcbiAgICAvLyAgICksXG4gICAgYXN5bmMgKGN0eDogRHVyYWJsZUNvbnRleHQsIHRhcmdldFJlc291cmNlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgIHJldHVybiBjdHgucnVuSW5DaGlsZENvbnRleHQoYHJlc291cmNlLSR7aW5kZXh9YCwgYXN5bmMgKGNoaWxkQ3R4OiBEdXJhYmxlQ29udGV4dCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcm9jZXNzT25lUmVzb3VyY2UoY2hpbGRDdHgsIHRhcmdldFJlc291cmNlLCBwYXJhbXMsIGluZGV4KTtcbiAgICAgICAgLy8gaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdza2lwcGVkJykge1xuICAgICAgICAvLyAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIC8vIH1cbiAgICAgICAgLy8gc2VuZCBzbGFjayB0aHJlYWQgbWVzc2FnZVxuICAgICAgICBhd2FpdCBjaGlsZEN0eC5zdGVwKCdwb3N0LXNsYWNrLWNoaWxkLW1lc3NhZ2VzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGRpc3BsYXkgPSBnZXRTdGF0ZURpc3BsYXkocmVzdWx0LnN0YXR1cyk7XG5cbiAgICAgICAgICByZXR1cm4gY2xpZW50LmNoYXQucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgICAgIHRocmVhZF90czogc2xhY2tQYXJlbnRNZXNzYWdlUmVzdWx0Py50cyxcbiAgICAgICAgICAgIGF0dGFjaG1lbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjb2xvcjogJyMzNmE2NGYnLFxuICAgICAgICAgICAgICAgIHByZXRleHQ6IGAke2Rpc3BsYXk/LmVtb2ppfSBUaGUgc3RhdHVzIG9mIHRoZSBFQzIgSW5zdGFuY2UgJHtyZXN1bHQuaWRlbnRpZmllcn0gY2hhbmdlZCB0byAke2Rpc3BsYXk/Lm5hbWV9IGR1ZSB0byB0aGUgc2NoZWR1bGUuYCxcbiAgICAgICAgICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICAgICAgICAgIHsgdGl0bGU6ICdBY2NvdW50JywgdmFsdWU6IHJlc3VsdC5hY2NvdW50LCBzaG9ydDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgeyB0aXRsZTogJ1JlZ2lvbicsIHZhbHVlOiByZXN1bHQucmVnaW9uLCBzaG9ydDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgeyB0aXRsZTogJ0lkZW50aWZpZXInLCB2YWx1ZTogcmVzdWx0LmlkZW50aWZpZXIsIHNob3J0OiB0cnVlIH0sXG4gICAgICAgICAgICAgICAgICB7IHRpdGxlOiAnU3RhdHVzJywgdmFsdWU6IChkaXNwbGF5Py5uYW1lID8/ICdVbmtub3duJyksIHNob3J0OiB0cnVlIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfSxcbiAgICB7IG1heENvbmN1cnJlbmN5OiAxMCB9LFxuICApO1xuXG4gIGNvbnN0IHJlc3VsdExpc3QgPSBBcnJheS5pc0FycmF5KHJlc3VsdHMpID8gcmVzdWx0cyA6IFtdO1xuICByZXR1cm4ge1xuICAgIHN0YXR1czogJ0NvbXBsZXRlZCcgYXMgY29uc3QsXG4gICAgcHJvY2Vzc2VkOiB0YXJnZXRSZXNvdXJjZXMubGVuZ3RoLFxuICAgIHJlc3VsdHM6IHJlc3VsdExpc3QsXG4gIH07XG59KTtcbiJdfQ==
|
|
261
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVubmluZy1zY2hlZHVsZXIubGFtYmRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Z1bmNzL3J1bm5pbmctc2NoZWR1bGVyLmxhbWJkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7R0FPRzs7O0FBRUgsNEVBQTBGO0FBQzFGLG9EQUs2QjtBQUM3QixvR0FBa0g7QUFDbEgsNENBQTJDO0FBQzNDLHlFQUEwRDtBQUMxRCxxREFBZ0Q7QUFDaEQsaUZBQXNFO0FBRXRFLHlFQUF5RTtBQUN6RSxNQUFNLFVBQVUsR0FBRztJQUNqQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFO0lBQ2xELEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7Q0FDMUMsQ0FBQztBQUVYLHVFQUF1RTtBQUN2RSxNQUFNLDBCQUEwQixHQUFHLEVBQUUsQ0FBQztBQXNCdEM7Ozs7O0dBS0c7QUFDSCxNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQWUsRUFBK0MsRUFBRTtJQUN2RixNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLE9BQU8sQ0FBQyxDQUFDO0lBQzFELE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUN0RSxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxrQkFBa0IsR0FBRyxLQUFLLEVBQzlCLEdBQW1CLEVBQ25CLGNBQXNCLEVBQ3RCLE1BQWdDLEVBQ2hDLGFBQXFCLEVBQytFLEVBQUU7SUFDdEcsTUFBTSxL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Q0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDhCQUE4QixFQUFFO1FBQzlDLFNBQVMsRUFBRSxlQUFlLENBQUMsTUFBTTtRQUNqQyxXQUFXLEVBQUUsVUFBVSxDQUFDLE1BQU07S0FDL0IsQ0FBQyxDQUFDO0lBQ0gsT0FBTztRQUNMLE1BQU0sRUFBRSxXQUFvQjtRQUM1QixTQUFTLEVBQUUsZUFBZSxDQUFDLE1BQU07UUFDakMsT0FBTyxFQUFFLFVBQVU7S0FDcEIsQ0FBQztBQUNKLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBFQzIgUnVubmluZyBTY2hlZHVsZXIg4oCTIER1cmFibGUgRnVuY3Rpb25zIGltcGxlbWVudGF0aW9uLlxuICpcbiAqIEltcGxlbWVudHMgdGhlIHJ1bm5pbmctY29udHJvbCBmbG93IHVzaW5nIEFXUyBMYW1iZGEgRHVyYWJsZSBFeGVjdXRpb24uXG4gKiBTdGVwIGNoZWNrcG9pbnRzLCB3YWl0IChubyBjaGFyZ2UpLCBhbmQgcGFyYWxsZWwgbWFwIHByb3ZpZGUgYSBmbG93IGVxdWl2YWxlbnQgdG8gU3RlcCBGdW5jdGlvbnMuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9kdXJhYmxlLWV4ZWN1dGlvbi1zZGsuaHRtbFxuICovXG5cbmltcG9ydCB7IHdpdGhEdXJhYmxlRXhlY3V0aW9uLCB0eXBlIER1cmFibGVDb250ZXh0IH0gZnJvbSAnQGF3cy9kdXJhYmxlLWV4ZWN1dGlvbi1zZGstanMnO1xuaW1wb3J0IHtcbiAgRUMyQ2xpZW50LFxuICBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmQsXG4gIFN0YXJ0SW5zdGFuY2VzQ29tbWFuZCxcbiAgU3RvcEluc3RhbmNlc0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1lYzInO1xuaW1wb3J0IHsgR2V0UmVzb3VyY2VzQ29tbWFuZCwgUmVzb3VyY2VHcm91cHNUYWdnaW5nQVBJQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXJlc291cmNlLWdyb3Vwcy10YWdnaW5nLWFwaSc7XG5pbXBvcnQgeyBXZWJDbGllbnQgfSBmcm9tICdAc2xhY2svd2ViLWFwaSc7XG5pbXBvcnQgeyBzZWNyZXRGZXRjaGVyIH0gZnJvbSAnYXdzLWxhbWJkYS1zZWNyZXQtZmV0Y2hlcic7XG5pbXBvcnQgeyBTYWZlRW52R2V0dGVyIH0gZnJvbSAnc2FmZS1lbnYtZ2V0dGVyJztcbmltcG9ydCB7IGlzRGVzaXJlZFN0YWJsZVN0YXRlIH0gZnJvbSAnLi9ydW5uaW5nLXNjaGVkdWxlci1wcmVkaWNhdGVzJztcblxuLyoqIE1hcHBpbmcgb2YgRUMyIGluc3RhbmNlIHN0YXRlIHRvIGRpc3BsYXkgbmFtZSBhbmQgZW1vamkgZm9yIFNsYWNrLiAqL1xuY29uc3QgU1RBVEVfTElTVCA9IFtcbiAgeyBuYW1lOiAnUlVOTklORycsIGVtb2ppOiAn8J+YhicsIHN0YXRlOiAncnVubmluZycgfSxcbiAgeyBuYW1lOiAnU1RPUFBFRCcsIGVtb2ppOiAn8J+YtCcsIHN0YXRlOiAnc3RvcHBlZCcgfSxcbl0gYXMgY29uc3Q7XG5cbi8qKiBTZWNvbmRzIHRvIHdhaXQgYmV0d2VlbiBwb2xsaW5nIGluc3RhbmNlIHN0YXRlIGFmdGVyIHN0YXJ0L3N0b3AuICovXG5jb25zdCBTVEFUVVNfQ0hBTkdFX1dBSVRfU0VDT05EUyA9IDIwO1xuXG4vKiogRXZlbnQgcGF5bG9hZCBmcm9tIEV2ZW50QnJpZGdlIFNjaGVkdWxlciBpbnZva2luZyB0aGlzIExhbWJkYS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NoZWR1bGVyRXZlbnQge1xuICBQYXJhbXM6IHtcbiAgICAvKiogVGFnIGtleSB1c2VkIHRvIHNlbGVjdCBFQzIgaW5zdGFuY2VzLiAqL1xuICAgIFRhZ0tleTogc3RyaW5nO1xuICAgIC8qKiBUYWcgdmFsdWVzIHRvIG1hdGNoLiAqL1xuICAgIFRhZ1ZhbHVlczogc3RyaW5nW107XG4gICAgLyoqIFdoZXRoZXIgdG8gc3RhcnQgb3Igc3RvcCBpbnN0YW5jZXMuICovXG4gICAgTW9kZTogJ1N0YXJ0JyB8ICdTdG9wJztcbiAgfTtcbn1cblxuLyoqIFNsYWNrIGNyZWRlbnRpYWxzIGFuZCBkZWZhdWx0IGNoYW5uZWwgbG9hZGVkIGZyb20gU2VjcmV0cyBNYW5hZ2VyIChgU0xBQ0tfU0VDUkVUX05BTUVgKS4gKi9cbmludGVyZmFjZSBTbGFja1NlY3JldCB7XG4gIC8qKiBTbGFjayBib3QgdG9rZW4gZm9yIHRoZSBTbGFjayBgV2ViQ2xpZW50YC4gKi9cbiAgdG9rZW46IHN0cmluZztcbiAgLyoqIENoYW5uZWwgSUQgb3IgbmFtZSBwYXNzZWQgdG8gYGNoYXQucG9zdE1lc3NhZ2VgLiAqL1xuICBjaGFubmVsOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmV0dXJucyBkaXNwbGF5IG5hbWUgYW5kIGVtb2ppIGZvciBhbiBFQzIgaW5zdGFuY2Ugc3RhdGUuXG4gKlxuICogQHBhcmFtIGN1cnJlbnQgLSBDdXJyZW50IGluc3RhbmNlIHN0YXRlIChlLmcuICdydW5uaW5nJywgJ3N0b3BwZWQnKS5cbiAqIEByZXR1cm5zIERpc3BsYXkgaW5mbyBvciB1bmRlZmluZWQgaWYgc3RhdGUgaXMgbm90IGluIFNUQVRFX0xJU1QuXG4gKi9cbmNvbnN0IGdldFN0YXRlRGlzcGxheSA9IChjdXJyZW50OiBzdHJpbmcpOiB7IGVtb2ppOiBzdHJpbmc7IG5hbWU6IHN0cmluZyB9IHwgdW5kZWZpbmVkID0+IHtcbiAgY29uc3QgZm91bmQgPSBTVEFURV9MSVNULmZpbmQoKHMpID0+IHMuc3RhdGUgPT09IGN1cnJlbnQpO1xuICByZXR1cm4gZm91bmQgPyB7IGVtb2ppOiBmb3VuZC5lbW9qaSwgbmFtZTogZm91bmQubmFtZSB9IDogdW5kZWZpbmVkO1xufTtcblxuLyoqXG4gKiBQcm9jZXNzZXMgb25lIEVDMiBpbnN0YW5jZTogZGVzY3JpYmVzIHN0YXRlLCBpc3N1ZXMgc3RhcnQvc3RvcCB3aGVuIG5lZWRlZCwgdGhlbiBwb2xscyB1bnRpbFxuICoge0BsaW5rIGlzRGVzaXJlZFN0YWJsZVN0YXRlfSBpcyBzYXRpc2ZpZWQgKGR1cmFibGUgYHN0ZXBgIC8gYHdhaXRgIGJldHdlZW4gYXR0ZW1wdHMpLlxuICpcbiAqIEBwYXJhbSBjdHggLSBEdXJhYmxlIGV4ZWN1dGlvbiBjb250ZXh0IChjaGlsZCBjb250ZXh0IHBlciBpbnN0YW5jZSByZWNvbW1lbmRlZCkuXG4gKiBAcGFyYW0gdGFyZ2V0UmVzb3VyY2UgLSBFQzIgaW5zdGFuY2UgQVJOLlxuICogQHBhcmFtIHBhcmFtcyAtIFNjaGVkdWxlciBwYXJhbXMgKGBUYWdLZXlgLCBgVGFnVmFsdWVzYCwgYE1vZGVgKS5cbiAqIEBwYXJhbSByZXNvdXJjZUluZGV4IC0gSW5kZXggdXNlZCBpbiBkdXJhYmxlIHN0ZXAgbmFtZXMgZm9yIHRoaXMgcmVzb3VyY2UuXG4gKiBAcmV0dXJucyBGaW5hbCByZXNvdXJjZSBBUk4sIEVDMiBzdGF0ZSBuYW1lLCBwYXJzZWQgYWNjb3VudCwgcmVnaW9uLCBhbmQgaW5zdGFuY2UgaWQuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHN0YXRlIGlzIG5laXRoZXIgYWN0aW9uYWJsZSwgdHJhbnNpdGlvbmluZywgbm9yIHRoZSBkZXNpcmVkIHN0YWJsZSBzdGF0ZS5cbiAqL1xuY29uc3QgcHJvY2Vzc09uZVJlc291cmNlID0gYXN5bmMgKFxuICBjdHg6IER1cmFibGVDb250ZXh0LFxuICB0YXJnZXRSZXNvdXJjZTogc3RyaW5nLFxuICBwYXJhbXM6IFNjaGVkdWxlckV2ZW50WydQYXJhbXMnXSxcbiAgcmVzb3VyY2VJbmRleDogbnVtYmVyLFxuKTogUHJvbWlzZTx7IHJlc291cmNlOiBzdHJpbmc7IHN0YXR1czogc3RyaW5nOyBhY2NvdW50OiBzdHJpbmc7IHJlZ2lvbjogc3RyaW5nOyBpZGVudGlmaWVyOiBzdHJpbmcgfT4gPT4ge1xuICBjb25zdCBwYXJ0cyA9IHRhcmdldFJlc291cmNlLnNwbGl0KCcvJyk7XG4gIGNvbnN0IGlkZW50aWZpZXIgPSBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSA/PyAndW5rbm93bic7XG4gIGNvbnN0IGFyblBhcnRzID0gdGFyZ2V0UmVzb3VyY2Uuc3BsaXQoJzonKTtcbiAgY29uc3QgYWNjb3VudCA9IGFyblBhcnRzWzRdID8/ICcnO1xuICBjb25zdCByZWdpb24gPSBhcm5QYXJ0c1szXSA/PyAnJztcbiAgY29uc3Qgc3RlcFByZWZpeCA9IGByZXNvdXJjZS0ke3Jlc291cmNlSW5kZXh9LSR7aWRlbnRpZmllcn1gO1xuXG4gIGN0eC5sb2dnZXIuaW5mbygncHJvY2Vzc09uZVJlc291cmNlOiBzdGFydCcsIHtcbiAgICByZXNvdXJjZUluZGV4LFxuICAgIGlkZW50aWZpZXIsXG4gICAgcmVnaW9uLFxuICAgIGFjY291bnQsXG4gICAgbW9kZTogcGFyYW1zLk1vZGUsXG4gIH0pO1xuXG4gIGxldCBsb29wQ291bnQgPSAwO1xuICBsZXQgY3VycmVudFN0YXRlID0gJyc7XG4gIGRvIHtcbiAgICBjdXJyZW50U3RhdGUgPSBhd2FpdCBjdHguc3RlcChgJHtzdGVwUHJlZml4fS1kZXNjcmliZS0ke2xvb3BDb3VudH1gLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBlYzIgPSBuZXcgRUMyQ2xpZW50KHt9KTtcbiAgICAgIGNvbnN0IG91dCA9IGF3YWl0IGVjMi5zZW5kKG5ldyBEZXNjcmliZUluc3RhbmNlc0NvbW1hbmQoeyBJbnN0YW5jZUlkczogW2lkZW50aWZpZXJdIH0pKTtcbiAgICAgIHJldHVybiBvdXQuUmVzZXJ2YXRpb25zPy5bMF0/Lkluc3RhbmNlcz8uWzBdPy5TdGF0ZT8uTmFtZSA/PyAndW5rbm93bic7XG4gICAgfSk7XG5cbiAgICBjdHgubG9nZ2VyLmluZm8oJ3Byb2Nlc3NPbmVSZXNvdXJjZTogZGVzY3JpYmVkJywge1xuICAgICAgaWRlbnRpZmllcixcbiAgICAgIGxvb3BDb3VudCxcbiAgICAgIGN1cnJlbnRTdGF0ZSxcbiAgICAgIG1vZGU6IHBhcmFtcy5Nb2RlLFxuICAgIH0pO1xuXG4gICAgY29uc3QgbW9kZSA9IHBhcmFtcy5Nb2RlO1xuXG4gICAgaWYgKG1vZGUgPT09ICdTdGFydCcgJiYgY3VycmVudFN0YXRlID09PSAnc3RvcHBlZCcpIHtcbiAgICAgIGN0eC5sb2dnZXIuaW5mbygncHJvY2Vzc09uZVJlc291cmNlOiBzdGFydGluZyBpbnN0YW5jZScsIHsgaWRlbnRpZmllciwgbG9vcENvdW50IH0pO1xuICAgICAgYXdhaXQgY3R4LnN0ZXAoYCR7c3RlcFByZWZpeH0tc3RhcnQtJHtsb29wQ291bnR9YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBlYzIgPSBuZXcgRUMyQ2xpZW50KHt9KTtcbiAgICAgICAgYXdhaXQgZWMyLnNlbmQobmV3IFN0YXJ0SW5zdGFuY2VzQ29tbWFuZCh7IEluc3RhbmNlSWRzOiBbaWRlbnRpZmllcl0gfSkpO1xuICAgICAgfSk7XG4gICAgICBjdHgubG9nZ2VyLmluZm8oJ3Byb2Nlc3NPbmVSZXNvdXJjZTogd2FpdCBhZnRlciBzdGFydCcsIHtcbiAgICAgICAgaWRlbnRpZmllcixcbiAgICAgICAgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IGN0eC53YWl0KHsgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMgfSk7XG4gICAgICBsb29wQ291bnQgKz0gMTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChtb2RlID09PSAnU3RvcCcgJiYgY3VycmVudFN0YXRlID09PSAncnVubmluZycpIHtcbiAgICAgIGN0eC5sb2dnZXIuaW5mbygncHJvY2Vzc09uZVJlc291cmNlOiBzdG9wcGluZyBpbnN0YW5jZScsIHsgaWRlbnRpZmllciwgbG9vcENvdW50IH0pO1xuICAgICAgYXdhaXQgY3R4LnN0ZXAoYCR7c3RlcFByZWZpeH0tc3RvcC0ke2xvb3BDb3VudH1gLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGVjMiA9IG5ldyBFQzJDbGllbnQoe30pO1xuICAgICAgICBhd2FpdCBlYzIuc2VuZChuZXcgU3RvcEluc3RhbmNlc0NvbW1hbmQoeyBJbnN0YW5jZUlkczogW2lkZW50aWZpZXJdIH0pKTtcbiAgICAgIH0pO1xuICAgICAgY3R4LmxvZ2dlci5pbmZvKCdwcm9jZXNzT25lUmVzb3VyY2U6IHdhaXQgYWZ0ZXIgc3RvcCcsIHtcbiAgICAgICAgaWRlbnRpZmllcixcbiAgICAgICAgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IGN0eC53YWl0KHsgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMgfSk7XG4gICAgICBsb29wQ291bnQgKz0gMTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmICghaXNEZXNpcmVkU3RhYmxlU3RhdGUobW9kZSwgY3VycmVudFN0YXRlKSkge1xuICAgICAgY29uc3QgdHJhbnNpdGlvbmluZyA9XG4gICAgICAgIChtb2RlID09PSAnU3RhcnQnICYmIGN1cnJlbnRTdGF0ZSA9PT0gJ3BlbmRpbmcnKSB8fFxuICAgICAgICAobW9kZSA9PT0gJ1N0b3AnICYmIChjdXJyZW50U3RhdGUgPT09ICdzdG9wcGluZycgfHwgY3VycmVudFN0YXRlID09PSAnc2h1dHRpbmctZG93bicpKTtcblxuICAgICAgaWYgKHRyYW5zaXRpb25pbmcpIHtcbiAgICAgICAgY3R4LmxvZ2dlci5pbmZvKCdwcm9jZXNzT25lUmVzb3VyY2U6IHdhaXQgd2hpbGUgdHJhbnNpdGlvbmluZycsIHtcbiAgICAgICAgICBpZGVudGlmaWVyLFxuICAgICAgICAgIGxvb3BDb3VudCxcbiAgICAgICAgICBjdXJyZW50U3RhdGUsXG4gICAgICAgICAgbW9kZSxcbiAgICAgICAgICBzZWNvbmRzOiBTVEFUVVNfQ0hBTkdFX1dBSVRfU0VDT05EUyxcbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IGN0eC53YWl0KHsgc2Vjb25kczogU1RBVFVTX0NIQU5HRV9XQUlUX1NFQ09ORFMgfSk7XG4gICAgICAgIGxvb3BDb3VudCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY3R4LmxvZ2dlci5lcnJvcigncHJvY2Vzc09uZVJlc291cmNlOiB1bmV4cGVjdGVkIHN0YXRlJywge1xuICAgICAgICBpZGVudGlmaWVyLFxuICAgICAgICBtb2RlLFxuICAgICAgICBjdXJyZW50U3RhdGUsXG4gICAgICAgIGxvb3BDb3VudCxcbiAgICAgIH0pO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnN0YW5jZSBzdGF0dXMgZmFpbDogbW9kZT0ke21vZGV9IGN1cnJlbnRTdGF0ZT0ke2N1cnJlbnRTdGF0ZX1gKTtcbiAgICB9XG4gIH0gd2hpbGUgKCFpc0Rlc2lyZWRTdGFibGVTdGF0ZShwYXJhbXMuTW9kZSwgY3VycmVudFN0YXRlKSk7XG5cbiAgY3R4LmxvZ2dlci5pbmZvKCdwcm9jZXNzT25lUmVzb3VyY2U6IHJlYWNoZWQgZGVzaXJlZCBzdGFibGUgc3RhdGUnLCB7XG4gICAgaWRlbnRpZmllcixcbiAgICBmaW5hbFN0YXRlOiBjdXJyZW50U3RhdGUsXG4gICAgbW9kZTogcGFyYW1zLk1vZGUsXG4gICAgbG9vcENvdW50LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIGlkZW50aWZpZXIsXG4gICAgYWNjb3VudCxcbiAgICByZWdpb24sXG4gICAgcmVzb3VyY2U6IHRhcmdldFJlc291cmNlLFxuICAgIHN0YXR1czogY3VycmVudFN0YXRlLFxuICB9O1xufTtcblxuLyoqXG4gKiBEdXJhYmxlIExhbWJkYSBlbnRyeSBwb2ludCBmb3IgdGhlIEVDMiBydW5uaW5nIHNjaGVkdWxlci5cbiAqXG4gKiBSZXNvbHZlcyBpbnN0YW5jZXMgdmlhIFJlc291cmNlIEdyb3VwcyBUYWdnaW5nIEFQSSwgcnVucyB7QGxpbmsgcHJvY2Vzc09uZVJlc291cmNlfSBmb3IgZWFjaCBBUk5cbiAqIGluIHBhcmFsbGVsIChib3VuZGVkIGNvbmN1cnJlbmN5KSwgcG9zdHMgYSBwYXJlbnQgU2xhY2sgbWVzc2FnZSBhbmQgcGVyLWluc3RhbmNlIHRocmVhZCByZXBsaWVzLFxuICogYW5kIHVzZXMgZHVyYWJsZSBgc3RlcGAgLyBgd2FpdGAgLyBgbWFwYCBzbyB0aGUgcnVuIGNhbiByZXN1bWUgYWNyb3NzIHN1c3BlbnNpb25zLlxuICpcbiAqIEBwYXJhbSBldmVudCAtIFBheWxvYWQgZnJvbSBFdmVudEJyaWRnZSBTY2hlZHVsZXI7IG11c3QgaW5jbHVkZSBgUGFyYW1zLlRhZ0tleWAsIGBQYXJhbXMuVGFnVmFsdWVzYCwgYFBhcmFtcy5Nb2RlYC5cbiAqIEBwYXJhbSBjdHggLSBSb290IGR1cmFibGUgZXhlY3V0aW9uIGNvbnRleHQuXG4gKiBAcmV0dXJuc1xuICogLSBgeyBzdGF0dXM6ICdUYXJnZXRSZXNvdXJjZXNOb3RGb3VuZCcgfWAgd2hlbiBubyBpbnN0YW5jZXMgbWF0Y2ggdGhlIHRhZyBmaWx0ZXIuXG4gKiAtIGB7IHN0YXR1czogJ0NvbXBsZXRlZCcsIHByb2Nlc3NlZCwgcmVzdWx0cyB9YCB3aGVuIGluc3RhbmNlcyB3ZXJlIGhhbmRsZWQgKGByZXN1bHRzYCBlbnRyaWVzIG1hdGNoIHtAbGluayBwcm9jZXNzT25lUmVzb3VyY2V9KS5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBgUGFyYW1zYCBpcyBpbnZhbGlkLCBgU0xBQ0tfU0VDUkVUX05BTUVgIGlzIHVuc2V0LCB0aGUgU2xhY2sgc2VjcmV0IGlzIGluY29tcGxldGUsIG9yIGluc3RhbmNlIHByb2Nlc3NpbmcgZmFpbHMuXG4gKi9cbmV4cG9ydCBjb25zdCBoYW5kbGVyID0gd2l0aER1cmFibGVFeGVjdXRpb24oYXN5bmMgKGV2ZW50OiBTY2hlZHVsZXJFdmVudCwgY3R4OiBEdXJhYmxlQ29udGV4dCkgPT4ge1xuXG4gIGNvbnN0IHBhcmFtcyA9IGV2ZW50LlBhcmFtcztcblxuICBjdHgubG9nZ2VyLmluZm8oJ3J1bm5pbmctc2NoZWR1bGVyOiBpbnZvY2F0aW9uJywge1xuICAgIG1vZGU6IHBhcmFtcz8uTW9kZSxcbiAgICB0YWdLZXk6IHBhcmFtcz8uVGFnS2V5LFxuICAgIHRhZ1ZhbHVlQ291bnQ6IHBhcmFtcz8uVGFnVmFsdWVzPy5sZW5ndGggPz8gMCxcbiAgfSk7XG5cbiAgaWYgKCFwYXJhbXM/LlRhZ0tleSB8fCAhcGFyYW1zPy5UYWdWYWx1ZXMgfHwgIXBhcmFtcz8uTW9kZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBldmVudDogUGFyYW1zLlRhZ0tleSwgUGFyYW1zLlRhZ1ZhbHVlcywgUGFyYW1zLk1vZGUgYXJlIHJlcXVpcmVkLicpO1xuICB9XG5cbiAgLy8gc2FmZSBnZXQgU2VjcmV0cyBuYW1lIGZyb20gZW52aXJvbm1lbnQgdmFyaWFibGVcbiAgY29uc3Qgc2xhY2tTZWNyZXROYW1lID0gU2FmZUVudkdldHRlci5nZXRFbnYoJ1NMQUNLX1NFQ1JFVF9OQU1FJyk7XG5cbiAgY29uc3Qgc2xhY2tTZWNyZXRWYWx1ZSA9IGF3YWl0IGN0eC5zdGVwKCdmZXRjaC1zbGFjay1zZWNyZXQnLCBhc3luYyAoKSA9PiB7XG4gICAgY3R4LmxvZ2dlci5pbmZvKCdydW5uaW5nLXNjaGVkdWxlcjogZmV0Y2hpbmcgU2xhY2sgc2VjcmV0JywgeyBzZWNyZXROYW1lOiBzbGFja1NlY3JldE5hbWUgfSk7XG4gICAgcmV0dXJuIHNlY3JldEZldGNoZXIuZ2V0U2VjcmV0VmFsdWU8U2xhY2tTZWNyZXQ+KHNsYWNrU2VjcmV0TmFtZSk7XG4gIH0pO1xuXG4gIGN0eC5sb2dnZXIuaW5mbygncnVubmluZy1zY2hlZHVsZXI6IFNsYWNrIHNlY3JldCBsb2FkZWQnKTtcblxuICBpZiAoIXNsYWNrU2VjcmV0VmFsdWU/LnRva2VuIHx8ICFzbGFja1NlY3JldFZhbHVlPy5jaGFubmVsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTbGFjayBzZWNyZXQgbXVzdCBjb250YWluIHRva2VuIGFuZCBjaGFubmVsLicpO1xuICB9XG5cbiAgY29uc3QgdGFyZ2V0UmVzb3VyY2VzID0gYXdhaXQgY3R4LnN0ZXAoJ2dldC10YXJnZXQtcmVzb3VyY2VzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBSZXNvdXJjZUdyb3Vwc1RhZ2dpbmdBUElDbGllbnQoe30pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudC5zZW5kKFxuICAgICAgbmV3IEdldFJlc291cmNlc0NvbW1hbmQoe1xuICAgICAgICBSZXNvdXJjZVR5cGVGaWx0ZXJzOiBbJ2VjMjppbnN0YW5jZSddLFxuICAgICAgICBUYWdGaWx0ZXJzOiBbeyBLZXk6IHBhcmFtcy5UYWdLZXksIFZhbHVlczogcGFyYW1zLlRhZ1ZhbHVlcyB9XSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgY29uc3QgYXJucyA9IChyZXN1bHQuUmVzb3VyY2VUYWdNYXBwaW5nTGlzdCA/PyBbXSlcbiAgICAgIC5tYXAoKG06IHsgUmVzb3VyY2VBUk4/OiBzdHJpbmcgfSkgPT4gbS5SZXNvdXJjZUFSTilcbiAgICAgIC5maWx0ZXIoKGFybjogc3RyaW5nIHwgdW5kZWZpbmVkKTogYXJuIGlzIHN0cmluZyA9PiBhcm4gIT0gbnVsbCk7XG4gICAgY3R4LmxvZ2dlci5pbmZvKCdydW5uaW5nLXNjaGVkdWxlcjogZ2V0LXRhcmdldC1yZXNvdXJjZXMgZG9uZScsIHsgY291bnQ6IGFybnMubGVuZ3RoIH0pO1xuICAgIHJldHVybiBhcm5zO1xuICB9KTtcblxuICBpZiAodGFyZ2V0UmVzb3VyY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIGN0eC5sb2dnZXIuaW5mbygncnVubmluZy1zY2hlZHVsZXI6IG5vIG1hdGNoaW5nIGluc3RhbmNlcycsIHsgdGFnS2V5OiBwYXJhbXMuVGFnS2V5IH0pO1xuICAgIHJldHVybiB7IHN0YXR1czogJ1RhcmdldFJlc291cmNlc05vdEZvdW5kJyBhcyBjb25zdCB9O1xuICB9XG5cbiAgY29uc3QgY2xpZW50ID0gbmV3IFdlYkNsaWVudChzbGFja1NlY3JldFZhbHVlLnRva2VuKTtcbiAgY29uc3QgY2hhbm5lbCA9IHNsYWNrU2VjcmV0VmFsdWUuY2hhbm5lbDtcblxuICBjdHgubG9nZ2VyLmluZm8oJ3J1bm5pbmctc2NoZWR1bGVyOiBwb3N0aW5nIHBhcmVudCBTbGFjayBtZXNzYWdlJywge1xuICAgIGluc3RhbmNlQ291bnQ6IHRhcmdldFJlc291cmNlcy5sZW5ndGgsXG4gIH0pO1xuXG4gIC8vIHNlbmQgc2xhY2sgbWVzc2FnZVxuICBjb25zdCBzbGFja1BhcmVudE1lc3NhZ2VSZXN1bHQgPSBhd2FpdCBjdHguc3RlcCgncG9zdC1zbGFjay1tZXNzYWdlcycsIGFzeW5jICgpID0+IHtcbiAgICByZXR1cm4gY2xpZW50LmNoYXQucG9zdE1lc3NhZ2Uoe1xuICAgICAgY2hhbm5lbCxcbiAgICAgIHRleHQ6IGAke3BhcmFtcy5Nb2RlID09PSAnU3RhcnQnID8gJ/CfmIYgU3RhcnRzJyA6ICfwn6WxIFN0b3BzJ30gdGhlIHNjaGVkdWxlZCBFQzIgSW5zdGFuY2UuYCxcbiAgICB9KTtcbiAgfSk7XG5cbiAgY3R4LmxvZ2dlci5pbmZvKCdydW5uaW5nLXNjaGVkdWxlcjogcGFyZW50IFNsYWNrIG1lc3NhZ2UgcG9zdGVkJywge1xuICAgIHRocmVhZFRzOiBzbGFja1BhcmVudE1lc3NhZ2VSZXN1bHQ/LnRzID8/IG51bGwsXG4gIH0pO1xuXG4gIGN0eC5sb2dnZXIuaW5mbygncnVubmluZy1zY2hlZHVsZXI6IHN0YXJ0aW5nIHBhcmFsbGVsIGluc3RhbmNlIHByb2Nlc3NpbmcnLCB7XG4gICAgY291bnQ6IHRhcmdldFJlc291cmNlcy5sZW5ndGgsXG4gICAgbWF4Q29uY3VycmVuY3k6IDEwLFxuICB9KTtcblxuICBjb25zdCByZXN1bHRzID0gYXdhaXQgY3R4Lm1hcChcbiAgICB0YXJnZXRSZXNvdXJjZXMsXG4gICAgLy8gYXN5bmMgKGN0eDogRHVyYWJsZUNvbnRleHQsIHRhcmdldFJlc291cmNlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+XG4gICAgLy8gICBjdHguc3RlcChgcHJvY2Vzcy1yZXNvdXJjZS0ke2luZGV4fWAsIGFzeW5jICgpID0+XG4gICAgLy8gICAgIHByb2Nlc3NPbmVSZXNvdXJjZShjdHgsIHRhcmdldFJlc291cmNlLCBwYXJhbXMsIGluZGV4KSxcbiAgICAvLyAgICksXG4gICAgYXN5bmMgKG1hcEN0eDogRHVyYWJsZUNvbnRleHQsIHRhcmdldFJlc291cmNlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgIHJldHVybiBtYXBDdHgucnVuSW5DaGlsZENvbnRleHQoYHJlc291cmNlLSR7aW5kZXh9YCwgYXN5bmMgKGNoaWxkQ3R4OiBEdXJhYmxlQ29udGV4dCkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwcm9jZXNzT25lUmVzb3VyY2UoY2hpbGRDdHgsIHRhcmdldFJlc291cmNlLCBwYXJhbXMsIGluZGV4KTtcbiAgICAgICAgLy8gaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdza2lwcGVkJykge1xuICAgICAgICAvLyAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIC8vIH1cbiAgICAgICAgY2hpbGRDdHgubG9nZ2VyLmluZm8oJ3J1bm5pbmctc2NoZWR1bGVyOiBwb3N0aW5nIHRocmVhZCBTbGFjayBtZXNzYWdlJywge1xuICAgICAgICAgIGluZGV4LFxuICAgICAgICAgIGlkZW50aWZpZXI6IHJlc3VsdC5pZGVudGlmaWVyLFxuICAgICAgICAgIHN0YXR1czogcmVzdWx0LnN0YXR1cyxcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIHNlbmQgc2xhY2sgdGhyZWFkIG1lc3NhZ2VcbiAgICAgICAgYXdhaXQgY2hpbGRDdHguc3RlcCgncG9zdC1zbGFjay1jaGlsZC1tZXNzYWdlcycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBkaXNwbGF5ID0gZ2V0U3RhdGVEaXNwbGF5KHJlc3VsdC5zdGF0dXMpO1xuXG4gICAgICAgICAgcmV0dXJuIGNsaWVudC5jaGF0LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNoYW5uZWwsXG4gICAgICAgICAgICB0aHJlYWRfdHM6IHNsYWNrUGFyZW50TWVzc2FnZVJlc3VsdD8udHMsXG4gICAgICAgICAgICBhdHRhY2htZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgY29sb3I6ICcjMzZhNjRmJyxcbiAgICAgICAgICAgICAgICBwcmV0ZXh0OiBgJHtkaXNwbGF5Py5lbW9qaX0gVGhlIHN0YXR1cyBvZiB0aGUgRUMyIEluc3RhbmNlICR7cmVzdWx0LmlkZW50aWZpZXJ9IGNoYW5nZWQgdG8gJHtkaXNwbGF5Py5uYW1lfSBkdWUgdG8gdGhlIHNjaGVkdWxlLmAsXG4gICAgICAgICAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgICAgICAgICB7IHRpdGxlOiAnQWNjb3VudCcsIHZhbHVlOiByZXN1bHQuYWNjb3VudCwgc2hvcnQ6IHRydWUgfSxcbiAgICAgICAgICAgICAgICAgIHsgdGl0bGU6ICdSZWdpb24nLCB2YWx1ZTogcmVzdWx0LnJlZ2lvbiwgc2hvcnQ6IHRydWUgfSxcbiAgICAgICAgICAgICAgICAgIHsgdGl0bGU6ICdJZGVudGlmaWVyJywgdmFsdWU6IHJlc3VsdC5pZGVudGlmaWVyLCBzaG9ydDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgICAgeyB0aXRsZTogJ1N0YXR1cycsIHZhbHVlOiAoZGlzcGxheT8ubmFtZSA/PyAnVW5rbm93bicpLCBzaG9ydDogdHJ1ZSB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgeyBtYXhDb25jdXJyZW5jeTogMTAgfSxcbiAgKTtcblxuICBjb25zdCByZXN1bHRMaXN0ID0gQXJyYXkuaXNBcnJheShyZXN1bHRzKSA/IHJlc3VsdHMgOiBbXTtcbiAgY3R4LmxvZ2dlci5pbmZvKCdydW5uaW5nLXNjaGVkdWxlcjogY29tcGxldGVkJywge1xuICAgIHByb2Nlc3NlZDogdGFyZ2V0UmVzb3VyY2VzLmxlbmd0aCxcbiAgICByZXN1bHRDb3VudDogcmVzdWx0TGlzdC5sZW5ndGgsXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIHN0YXR1czogJ0NvbXBsZXRlZCcgYXMgY29uc3QsXG4gICAgcHJvY2Vzc2VkOiB0YXJnZXRSZXNvdXJjZXMubGVuZ3RoLFxuICAgIHJlc3VsdHM6IHJlc3VsdExpc3QsXG4gIH07XG59KTtcbiJdfQ==
|
|
@@ -29,5 +29,5 @@ class EC2InstanceRunningScheduleStack extends aws_cdk_lib_1.Stack {
|
|
|
29
29
|
}
|
|
30
30
|
exports.EC2InstanceRunningScheduleStack = EC2InstanceRunningScheduleStack;
|
|
31
31
|
_a = JSII_RTTI_SYMBOL_1;
|
|
32
|
-
EC2InstanceRunningScheduleStack[_a] = { fqn: "aws-ec2-instance-running-scheduler.EC2InstanceRunningScheduleStack", version: "3.0
|
|
32
|
+
EC2InstanceRunningScheduleStack[_a] = { fqn: "aws-ec2-instance-running-scheduler.EC2InstanceRunningScheduleStack", version: "3.1.0" };
|
|
33
33
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWMyLWluc3RhbmNlLXJ1bm5pbmctc2NoZWR1bGUtc3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RhY2tzL2VjMi1pbnN0YW5jZS1ydW5uaW5nLXNjaGVkdWxlLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNkNBQWdEO0FBRWhELGlHQUE4SDtBQWtCOUg7O0dBRUc7QUFDSCxNQUFhLCtCQUFnQyxTQUFRLG1CQUFLO0lBQ3hEOzs7Ozs7T0FNRztJQUNILFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBMkM7UUFDbkYsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFeEIsSUFBSSw0REFBMkIsQ0FBQyxJQUFJLEVBQUUsNkJBQTZCLEVBQUU7WUFDbkUsY0FBYyxFQUFFLEtBQUssQ0FBQyxjQUFjO1lBQ3BDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0I7WUFDeEMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTtZQUNoQyxhQUFhLEVBQUUsS0FBSyxDQUFDLGFBQWE7U0FDbkMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUFsQkgsMEVBbUJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3RhY2ssIFN0YWNrUHJvcHMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEVDMkluc3RhbmNlUnVubmluZ1NjaGVkdWxlciwgVGFyZ2V0UmVzb3VyY2UsIFNlY3JldHMsIFNjaGVkdWxlIH0gZnJvbSAnLi4vY29uc3RydWN0cy9lYzItaW5zdGFuY2UtcnVubmluZy1zY2hlZHVsZXInO1xuXG4vKipcbiAqIFByb3BzIGZvciB0aGUgRUMyIGluc3RhbmNlIHJ1bm5pbmcgc2NoZWR1bGUgQ0RLIHN0YWNrLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVDMkluc3RhbmNlUnVubmluZ1NjaGVkdWxlU3RhY2tQcm9wcyBleHRlbmRzIFN0YWNrUHJvcHMge1xuICAvKiogVGFnLWJhc2VkIHRhcmdldCByZXNvdXJjZSBmb3IgRUMyIGluc3RhbmNlcyB0byBzdGFydC9zdG9wLiAqL1xuICByZWFkb25seSB0YXJnZXRSZXNvdXJjZTogVGFyZ2V0UmVzb3VyY2U7XG4gIC8qKiBXaGV0aGVyIHNjaGVkdWxpbmcgaXMgZW5hYmxlZC4gRGVmYXVsdHMgdG8gdHJ1ZSBpZiBvbWl0dGVkLiAqL1xuICByZWFkb25seSBlbmFibGVTY2hlZHVsaW5nPzogYm9vbGVhbjtcbiAgLyoqIFNlY3JldHMgKGUuZy4gU2xhY2spIGZvciB0aGUgc2NoZWR1bGVyLiAqL1xuICByZWFkb25seSBzZWNyZXRzOiBTZWNyZXRzO1xuICAvKiogQ3JvbiBzY2hlZHVsZSBmb3Igc3RvcHBpbmcgaW5zdGFuY2VzLiAqL1xuICByZWFkb25seSBzdG9wU2NoZWR1bGU/OiBTY2hlZHVsZTtcbiAgLyoqIENyb24gc2NoZWR1bGUgZm9yIHN0YXJ0aW5nIGluc3RhbmNlcy4gKi9cbiAgcmVhZG9ubHkgc3RhcnRTY2hlZHVsZT86IFNjaGVkdWxlO1xufVxuXG4vKipcbiAqIENESyBTdGFjayB0aGF0IGRlcGxveXMgdGhlIEVDMiBpbnN0YW5jZSBydW5uaW5nIHNjaGVkdWxlciAoRXZlbnRCcmlkZ2UgU2NoZWR1bGVyICsgRHVyYWJsZSBMYW1iZGEpLlxuICovXG5leHBvcnQgY2xhc3MgRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVTdGFjayBleHRlbmRzIFN0YWNrIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIHN0YWNrIGFuZCB0aGUgRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVyIGNvbnN0cnVjdC5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIC0gUGFyZW50IGNvbnN0cnVjdC5cbiAgICogQHBhcmFtIGlkIC0gU3RhY2sgaWQuXG4gICAqIEBwYXJhbSBwcm9wcyAtIFN0YWNrIHByb3BzICh0YXJnZXQgcmVzb3VyY2UsIHNjaGVkdWxlcywgc2VjcmV0cykuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVTdGFja1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICBuZXcgRUMySW5zdGFuY2VSdW5uaW5nU2NoZWR1bGVyKHRoaXMsICdFQzJJbnN0YW5jZVJ1bm5pbmdTY2hlZHVsZXInLCB7XG4gICAgICB0YXJnZXRSZXNvdXJjZTogcHJvcHMudGFyZ2V0UmVzb3VyY2UsXG4gICAgICBlbmFibGVTY2hlZHVsaW5nOiBwcm9wcy5lbmFibGVTY2hlZHVsaW5nLFxuICAgICAgc2VjcmV0czogcHJvcHMuc2VjcmV0cyxcbiAgICAgIHN0b3BTY2hlZHVsZTogcHJvcHMuc3RvcFNjaGVkdWxlLFxuICAgICAgc3RhcnRTY2hlZHVsZTogcHJvcHMuc3RhcnRTY2hlZHVsZSxcbiAgICB9KTtcbiAgfVxufSJdfQ==
|
package/package.json
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"author": {
|
|
36
36
|
"name": "yicr",
|
|
37
37
|
"email": "yicr@users.noreply.github.com",
|
|
38
|
-
"organization":
|
|
38
|
+
"organization": false
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@aws-sdk/client-ec2": "^3",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"aws-sdk-client-mock-jest": "^2",
|
|
55
55
|
"commit-and-tag-version": "^12",
|
|
56
56
|
"constructs": "10.5.1",
|
|
57
|
-
"esbuild": "^0.
|
|
57
|
+
"esbuild": "^0.28.0",
|
|
58
58
|
"eslint": "^9",
|
|
59
59
|
"eslint-import-resolver-typescript": "^3.10.1",
|
|
60
60
|
"eslint-plugin-import": "^2.32.0",
|
|
@@ -65,8 +65,9 @@
|
|
|
65
65
|
"jsii-docgen": "^10.5.0",
|
|
66
66
|
"jsii-pacmak": "^1.127.0",
|
|
67
67
|
"jsii-rosetta": "5.9.x",
|
|
68
|
-
"projen": "^0.99.
|
|
69
|
-
"
|
|
68
|
+
"projen": "^0.99.34",
|
|
69
|
+
"safe-env-getter": "^0.2",
|
|
70
|
+
"ts-jest": "^29.4.9",
|
|
70
71
|
"ts-node": "^10.9.2",
|
|
71
72
|
"typescript": "5.9.x"
|
|
72
73
|
},
|
|
@@ -87,12 +88,19 @@
|
|
|
87
88
|
"engines": {
|
|
88
89
|
"node": ">= 20.0.0"
|
|
89
90
|
},
|
|
91
|
+
"devEngines": {
|
|
92
|
+
"packageManager": {
|
|
93
|
+
"name": "yarn",
|
|
94
|
+
"version": "<2.0.0",
|
|
95
|
+
"onFail": "ignore"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
90
98
|
"main": "lib/index.js",
|
|
91
99
|
"license": "Apache-2.0",
|
|
92
100
|
"publishConfig": {
|
|
93
101
|
"access": "public"
|
|
94
102
|
},
|
|
95
|
-
"version": "3.0
|
|
103
|
+
"version": "3.1.0",
|
|
96
104
|
"jest": {
|
|
97
105
|
"coverageProvider": "v8",
|
|
98
106
|
"testMatch": [
|
|
@@ -148,5 +156,6 @@
|
|
|
148
156
|
"rootDir": "src"
|
|
149
157
|
}
|
|
150
158
|
},
|
|
159
|
+
"packageManager": "yarn@1.22.22",
|
|
151
160
|
"//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
|
|
152
161
|
}
|