ec2-instance-running-scheduler 0.2.7 → 0.3.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 +357 -47
- package/API.md +402 -27
- package/README.md +55 -17
- package/assets/funcs/running-scheduler.lambda/index.js +333 -212
- package/assets/funcs/running-scheduler.lambda/index.js.map +4 -4
- package/lib/constructs/ec2-instance-running-scheduler.d.ts +31 -14
- package/lib/constructs/ec2-instance-running-scheduler.js +26 -13
- package/lib/constructs/running-scheduler-failure-detection.d.ts +87 -0
- package/lib/constructs/running-scheduler-failure-detection.js +185 -0
- package/lib/funcs/running-scheduler-predicates.d.ts +24 -24
- package/lib/funcs/running-scheduler-predicates.js +18 -18
- package/lib/funcs/running-scheduler-wait-config.d.ts +17 -0
- package/lib/funcs/running-scheduler-wait-config.js +21 -0
- package/lib/funcs/running-scheduler-wait-env.d.ts +9 -0
- package/lib/funcs/running-scheduler-wait-env.js +54 -0
- package/lib/funcs/running-scheduler.lambda.d.ts +11 -4
- package/lib/funcs/running-scheduler.lambda.js +88 -50
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -2
- package/lib/stacks/ec2-instance-running-schedule-stack.d.ts +9 -3
- package/lib/stacks/ec2-instance-running-schedule-stack.js +8 -3
- package/package.json +5 -6
- package/lib/funcs/running-scheduler-polling-config.d.ts +0 -17
- package/lib/funcs/running-scheduler-polling-config.js +0 -21
- package/lib/funcs/running-scheduler-polling-env.d.ts +0 -8
- package/lib/funcs/running-scheduler-polling-env.js +0 -53
package/README.md
CHANGED
|
@@ -6,18 +6,19 @@
|
|
|
6
6
|
[](https://github.com/gammarers-aws-cdk-constructs/ec2-instance-running-scheduler/releases)
|
|
7
7
|
[](https://constructs.dev/packages/ec2-instance-running-scheduler)
|
|
8
8
|
|
|
9
|
-
AWS CDK construct library 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**, issues start/stop, **
|
|
9
|
+
AWS CDK construct library 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**, issues start/stop, **waits until each instance reaches a stable 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** alongside JSON platform logs.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
13
|
- **Tag-based targeting** – Select EC2 instances by tag key and values (e.g. `Schedule` / `YES`) via `tag:GetResources`.
|
|
14
14
|
- **EventBridge Scheduler** – Separate cron rules for start and stop, with per-rule timezone (`aws-cdk-lib` `TimeZone`).
|
|
15
15
|
- **Durable Lambda** – One Lambda with AWS Lambda Durable Execution (`step`, `wait`, `map`, child contexts per instance) for long-running workflows without Step Functions.
|
|
16
|
-
- **Stable-state
|
|
17
|
-
- **Configurable
|
|
18
|
-
- **Validated environment variables** – The bundled handler parses
|
|
16
|
+
- **Stable-state waiting** – After start/stop, the function waits (20 seconds between attempts) and re-describes instances until `running` (start mode) or `stopped` (stop mode).
|
|
17
|
+
- **Configurable wait limits** – Per-instance **max loop count** and **max elapsed time** via `resourceWait` (default: 90 loops / 1800 seconds). Failures use explicit `ResourceWaitFailed:*` messages instead of running until the Durable execution timeout (construct default: 2 hours).
|
|
18
|
+
- **Validated environment variables** – The bundled handler parses env vars with **strict-env-resolver** (`StrictEnvResolver`). `SLACK_SECRET_NAME` is required; wait limits must be **finite positive numbers** (`> 0`).
|
|
19
19
|
- **Slack notifications** – Parent message plus threaded updates per instance; credentials from Secrets Manager JSON (`token`, `channel`). The construct sets **`SLACK_SECRET_NAME`** on the function.
|
|
20
|
-
- **Structured logging** – Durable execution **`ctx.logger`** for traceable JSON application logs (invocation, describe/start/stop/wait loops,
|
|
20
|
+
- **Structured logging** – Durable execution **`ctx.logger`** for traceable JSON application logs (invocation, describe/start/stop/wait loops, wait limit errors, Slack steps, completion).
|
|
21
|
+
- **Optional failure detection** – CloudWatch alarms and log-based metrics for Lambda errors, instance wait failures (`ResourceWaitFailed`), Slack post failures, and other handler `ERROR` logs. Optional SNS notifications via a caller-supplied topic (`failureDetection.alarmTopic`).
|
|
21
22
|
- **Scheduling toggle** – Enable or disable both schedules without removing the stack (`enableScheduling`).
|
|
22
23
|
- **Configurable schedules** – Optional cron overrides for start and stop (`minute`, `hour`, `week`, `timezone`); sensible defaults if omitted.
|
|
23
24
|
- **IAM and observability** – EC2 and tagging API permissions, Slack secret read grant, **Parameters and Secrets Lambda Extension**, JSON logging, and a dedicated log group (construct defaults).
|
|
@@ -49,11 +50,14 @@ Use the **construct** `EC2InstanceRunningScheduler` when embedding the scheduler
|
|
|
49
50
|
```typescript
|
|
50
51
|
import * as cdk from 'aws-cdk-lib';
|
|
51
52
|
import { TimeZone } from 'aws-cdk-lib';
|
|
53
|
+
import * as sns from 'aws-cdk-lib/aws-sns';
|
|
52
54
|
import { EC2InstanceRunningScheduler } from 'ec2-instance-running-scheduler';
|
|
53
55
|
|
|
54
56
|
const app = new cdk.App();
|
|
55
57
|
const stack = new cdk.Stack(app, 'MyStack');
|
|
56
58
|
|
|
59
|
+
const alarmTopic = new sns.Topic(stack, 'OpsAlerts');
|
|
60
|
+
|
|
57
61
|
new EC2InstanceRunningScheduler(stack, 'EC2InstanceRunningScheduler', {
|
|
58
62
|
targetResource: {
|
|
59
63
|
tagKey: 'Schedule',
|
|
@@ -75,22 +79,33 @@ new EC2InstanceRunningScheduler(stack, 'EC2InstanceRunningScheduler', {
|
|
|
75
79
|
week: 'MON-FRI',
|
|
76
80
|
},
|
|
77
81
|
enableScheduling: true,
|
|
78
|
-
|
|
82
|
+
resourceWait: {
|
|
79
83
|
maxLoopCount: 120,
|
|
80
84
|
maxElapsedSeconds: 3600,
|
|
81
85
|
},
|
|
86
|
+
failureDetection: {
|
|
87
|
+
enabled: true,
|
|
88
|
+
alarmTopic,
|
|
89
|
+
},
|
|
82
90
|
});
|
|
83
91
|
```
|
|
84
92
|
|
|
85
|
-
Use the **stack** `EC2InstanceRunningScheduleStack` when deploying the scheduler as its own stack. It accepts the same **targeting, schedules, secrets, and
|
|
93
|
+
Use the **stack** `EC2InstanceRunningScheduleStack` when deploying the scheduler as its own stack. It accepts the same **targeting, schedules, secrets, enable flag, and failure detection** as the construct (plus standard `StackProps` such as `env`). For **`resourceWait`**, use the construct directly or extend the stack in your app.
|
|
86
94
|
|
|
87
95
|
```typescript
|
|
88
96
|
import * as cdk from 'aws-cdk-lib';
|
|
89
97
|
import { TimeZone } from 'aws-cdk-lib';
|
|
98
|
+
import * as sns from 'aws-cdk-lib/aws-sns';
|
|
90
99
|
import { EC2InstanceRunningScheduleStack } from 'ec2-instance-running-scheduler';
|
|
91
100
|
|
|
92
101
|
const app = new cdk.App();
|
|
93
102
|
|
|
103
|
+
const alarmTopic = sns.Topic.fromTopicArn(
|
|
104
|
+
app,
|
|
105
|
+
'OpsAlerts',
|
|
106
|
+
'arn:aws:sns:ap-northeast-1:123456789012:ops-alerts',
|
|
107
|
+
);
|
|
108
|
+
|
|
94
109
|
new EC2InstanceRunningScheduleStack(app, 'EC2InstanceRunningScheduleStack', {
|
|
95
110
|
targetResource: {
|
|
96
111
|
tagKey: 'Schedule',
|
|
@@ -112,6 +127,10 @@ new EC2InstanceRunningScheduleStack(app, 'EC2InstanceRunningScheduleStack', {
|
|
|
112
127
|
week: 'MON-FRI',
|
|
113
128
|
},
|
|
114
129
|
enableScheduling: true,
|
|
130
|
+
failureDetection: {
|
|
131
|
+
enabled: true,
|
|
132
|
+
alarmTopic,
|
|
133
|
+
},
|
|
115
134
|
});
|
|
116
135
|
```
|
|
117
136
|
|
|
@@ -120,10 +139,10 @@ EventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues
|
|
|
120
139
|
| Variable | Source | Purpose |
|
|
121
140
|
|----------|--------|---------|
|
|
122
141
|
| `SLACK_SECRET_NAME` | `secrets.slackSecretName` | Secrets Manager secret for Slack (required) |
|
|
123
|
-
| `PROCESS_RESOURCE_MAX_LOOP_COUNT` | `
|
|
124
|
-
| `PROCESS_RESOURCE_MAX_ELAPSED_SECONDS` | `
|
|
142
|
+
| `PROCESS_RESOURCE_MAX_LOOP_COUNT` | `resourceWait.maxLoopCount` (default `90`) | Max describe/wait iterations per instance |
|
|
143
|
+
| `PROCESS_RESOURCE_MAX_ELAPSED_SECONDS` | `resourceWait.maxElapsedSeconds` (default `1800`) | Max wall-clock seconds waiting for one instance |
|
|
125
144
|
|
|
126
|
-
When you set
|
|
145
|
+
When you set wait limits via `resourceWait`, the construct writes them as decimal integer strings. At invocation the handler parses them with **strict-env-resolver**; each value must be a **finite number greater than zero**. Missing `SLACK_SECRET_NAME` or invalid env values cause `StrictEnvValidationError` at the start of an invocation.
|
|
127
146
|
|
|
128
147
|
## Options
|
|
129
148
|
|
|
@@ -136,11 +155,12 @@ When you set polling limits via `resourcePolling`, the construct writes them as
|
|
|
136
155
|
| `startSchedule` | `Schedule` | No | Cron for starting instances (default: `50 7 ? * MON-FRI *` in `Etc/UTC`). |
|
|
137
156
|
| `stopSchedule` | `Schedule` | No | Cron for stopping instances (default: `5 19 ? * MON-FRI *` in `Etc/UTC`). |
|
|
138
157
|
| `enableScheduling` | `boolean` | No | Whether both scheduler rules are enabled (default: `true`). |
|
|
139
|
-
| `
|
|
158
|
+
| `resourceWait` | `ResourceWaitLimits` | No | Per-instance wait caps (see below). |
|
|
159
|
+
| `failureDetection` | `FailureDetectionAlarms` | No | Optional CloudWatch alarms and log-based metrics (see below). |
|
|
140
160
|
|
|
141
161
|
### EC2InstanceRunningScheduleStack
|
|
142
162
|
|
|
143
|
-
Includes `targetResource`, `secrets`, `startSchedule`, `stopSchedule`, `enableScheduling`, and standard `StackProps`. Does **not** expose `
|
|
163
|
+
Includes `targetResource`, `secrets`, `startSchedule`, `stopSchedule`, `enableScheduling`, `failureDetection`, and standard `StackProps`. Does **not** expose `resourceWait`; use `EC2InstanceRunningScheduler` when you need custom wait limits.
|
|
144
164
|
|
|
145
165
|
### TargetResource
|
|
146
166
|
|
|
@@ -158,20 +178,38 @@ Includes `targetResource`, `secrets`, `startSchedule`, `stopSchedule`, `enableSc
|
|
|
158
178
|
|
|
159
179
|
- `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`).
|
|
160
180
|
|
|
161
|
-
###
|
|
181
|
+
### ResourceWaitLimits
|
|
162
182
|
|
|
163
183
|
Written to `PROCESS_RESOURCE_MAX_LOOP_COUNT` and `PROCESS_RESOURCE_MAX_ELAPSED_SECONDS` on the running scheduler Lambda.
|
|
164
184
|
|
|
165
|
-
- `maxLoopCount` – Maximum describe/
|
|
166
|
-
- `maxElapsedSeconds` – Maximum wall-clock seconds spent
|
|
185
|
+
- `maxLoopCount` – Maximum describe/wait loop iterations per instance (default: **90**). Must be a positive integer when set.
|
|
186
|
+
- `maxElapsedSeconds` – Maximum wall-clock seconds spent waiting for one instance to stabilize (default: **1800**, 30 minutes). Must be a positive integer when set.
|
|
187
|
+
|
|
188
|
+
When a limit is exceeded during waiting, the handler throws an error with prefix `ResourceWaitFailed:` (`MaxLoopCountExceeded`, `MaxElapsedTimeExceeded`, or `UnexpectedInstanceState` for unknown EC2 states).
|
|
189
|
+
|
|
190
|
+
### FailureDetectionAlarms
|
|
191
|
+
|
|
192
|
+
Optional operational failure detection. Alarms are created only when `enabled` is `true`.
|
|
193
|
+
|
|
194
|
+
- `enabled` – When `true`, creates four CloudWatch alarms and three log metric filters (default: disabled when omitted).
|
|
195
|
+
- `alarmTopic` – Optional `sns.ITopic` for alarm actions. The construct does **not** create an SNS topic; pass an existing or imported topic. When omitted, alarms are created without SNS actions.
|
|
196
|
+
|
|
197
|
+
When enabled, the construct creates:
|
|
198
|
+
|
|
199
|
+
| Alarm | Trigger |
|
|
200
|
+
|-------|---------|
|
|
201
|
+
| Lambda errors | `AWS/Lambda` `Errors` metric |
|
|
202
|
+
| Instance status failure | Log filter: `ResourceWaitFailed` |
|
|
203
|
+
| Slack post failure | Log filter: `running-scheduler: Slack post failed` |
|
|
204
|
+
| Durable execution failure | Other handler `ERROR` logs (excluding the above) |
|
|
167
205
|
|
|
168
|
-
|
|
206
|
+
Custom metrics are published under the `EC2InstanceRunningScheduler` namespace. Access the created alarms via `EC2InstanceRunningScheduler.failureDetection` when enabled.
|
|
169
207
|
|
|
170
208
|
## Requirements
|
|
171
209
|
|
|
172
210
|
- **Node.js** ≥ 20.0.0 (for developing or synthesizing CDK apps that depend on this package).
|
|
173
211
|
- **aws-cdk-lib** ^2.232.0 and **constructs** ^10.5.1 (peer dependencies).
|
|
174
|
-
- **AWS** – EventBridge Scheduler; Lambda with **Durable Execution** (Node.js **24.x** runtime in the construct; Durable Execution requires a supported Node.js runtime in your region), a **live alias**, **Parameters and Secrets Lambda Extension**; EC2 (`DescribeInstances`, `StartInstances`, `StopInstances`); Resource Groups Tagging API (`tag:GetResources`); Secrets Manager. The deployed function uses **arm64**, Durable Execution IAM policies, a 2-hour Durable execution timeout (construct default), and a bundled handler that loads secrets via **aws-lambda-secret-fetcher
|
|
212
|
+
- **AWS** – EventBridge Scheduler; Lambda with **Durable Execution** (Node.js **24.x** runtime in the construct; Durable Execution requires a supported Node.js runtime in your region), a **live alias**, **Parameters and Secrets Lambda Extension**; EC2 (`DescribeInstances`, `StartInstances`, `StopInstances`); Resource Groups Tagging API (`tag:GetResources`); Secrets Manager. The deployed function uses **arm64**, Durable Execution IAM policies, a 2-hour Durable execution timeout (construct default), and a bundled handler that loads secrets via **aws-lambda-secret-fetcher** (^0.6) and parses env vars via **strict-env-resolver** (^0.5). Secret fetch runs only inside Lambda (requires runtime `AWS_SESSION_TOKEN` and the extension layer); the library retries transient extension errors including cold-start "not ready" responses.
|
|
175
213
|
|
|
176
214
|
## License
|
|
177
215
|
|