ec2-instance-running-scheduler 0.3.6 → 0.4.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/API.md CHANGED
@@ -10,7 +10,11 @@ Each schedule invokes the function with `Params` (`TagKey`, `TagValues`, `Mode`)
10
10
  the Resource Groups Tagging API and EC2 APIs; Slack notifications use the secret named in {@link Secrets.slackSecretName}.
11
11
 
12
12
  Per-instance wait timeouts are configured via {@link EC2InstanceRunningSchedulerProps.resourceWait}
13
- and enforced in the handler before the Durable execution timeout. Optional CloudWatch failure
13
+ and enforced in the handler before the Durable execution timeout. Lambda memory, invoke timeout,
14
+ and map concurrency are set via {@link EC2InstanceRunningSchedulerProps.runtime}; Durable
15
+ execution timeout and history retention via {@link EC2InstanceRunningSchedulerProps.durable};
16
+ log retention via {@link EC2InstanceRunningSchedulerProps.logGroup}. Start/stop IAM is limited
17
+ to instances tagged as {@link TargetResource}. Optional CloudWatch failure
14
18
  detection is available via {@link EC2InstanceRunningSchedulerProps.failureDetection}.
15
19
 
16
20
  #### Initializers <a name="Initializers" id="ec2-instance-running-scheduler.EC2InstanceRunningScheduler.Initializer"></a>
@@ -25,7 +29,7 @@ new EC2InstanceRunningScheduler(scope: Construct, id: string, props: EC2Instance
25
29
  | --- | --- | --- |
26
30
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningScheduler.Initializer.parameter.scope">scope</a></code> | <code>constructs.Construct</code> | - Parent construct. |
27
31
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningScheduler.Initializer.parameter.id">id</a></code> | <code>string</code> | - Construct id. |
28
- | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningScheduler.Initializer.parameter.props">props</a></code> | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps">EC2InstanceRunningSchedulerProps</a></code> | - Target tags, schedules, Slack secret, schedule enable flag, optional {@link ResourceWaitLimits}, and optional {@link FailureDetectionAlarms}. |
32
+ | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningScheduler.Initializer.parameter.props">props</a></code> | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps">EC2InstanceRunningSchedulerProps</a></code> | - Target tags, schedules, Slack secret, schedule enable flag, optional {@link ResourceWaitLimits}, {@link RunningSchedulerRuntimeProps}, {@link RunningSchedulerDurableProps}, {@link RunningSchedulerLogGroupProps}, and optional {@link FailureDetectionAlarms}. |
29
33
 
30
34
  ---
31
35
 
@@ -49,7 +53,7 @@ Construct id.
49
53
 
50
54
  - *Type:* <a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps">EC2InstanceRunningSchedulerProps</a>
51
55
 
52
- Target tags, schedules, Slack secret, schedule enable flag, optional {@link ResourceWaitLimits}, and optional {@link FailureDetectionAlarms}.
56
+ Target tags, schedules, Slack secret, schedule enable flag, optional {@link ResourceWaitLimits}, {@link RunningSchedulerRuntimeProps}, {@link RunningSchedulerDurableProps}, {@link RunningSchedulerLogGroupProps}, and optional {@link FailureDetectionAlarms}.
53
57
 
54
58
  ---
55
59
 
@@ -170,8 +174,10 @@ Failure detection alarms, when {@link EC2InstanceRunningSchedulerProps.failureDe
170
174
  CDK stack that deploys the EC2 instance running scheduler (EventBridge Scheduler + Durable Lambda).
171
175
 
172
176
  Wires {@link EC2InstanceRunningScheduler} with targeting, schedules, secrets, scheduling toggle,
173
- and optional {@link FailureDetectionAlarms}. Does not expose {@link ResourceWaitLimits }; use the
174
- construct directly when custom per-instance wait limits are required.
177
+ and optional {@link FailureDetectionAlarms}. Does not expose {@link ResourceWaitLimits },
178
+ {@link RunningSchedulerRuntimeProps }, {@link RunningSchedulerDurableProps }, or
179
+ {@link RunningSchedulerLogGroupProps }; use the construct directly when custom runtime,
180
+ wait, durable, or log group settings are required.
175
181
 
176
182
  #### Initializers <a name="Initializers" id="ec2-instance-running-scheduler.EC2InstanceRunningScheduleStack.Initializer"></a>
177
183
 
@@ -1362,9 +1368,12 @@ const eC2InstanceRunningSchedulerProps: EC2InstanceRunningSchedulerProps = { ...
1362
1368
  | --- | --- | --- |
1363
1369
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.secrets">secrets</a></code> | <code><a href="#ec2-instance-running-scheduler.Secrets">Secrets</a></code> | Secrets (e.g. Slack) used for notifications. |
1364
1370
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.targetResource">targetResource</a></code> | <code><a href="#ec2-instance-running-scheduler.TargetResource">TargetResource</a></code> | Tag-based targeting for EC2 instances to start/stop. |
1371
+ | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.durable">durable</a></code> | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerDurableProps">RunningSchedulerDurableProps</a></code> | Durable Execution timeout and history retention. |
1365
1372
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.enableScheduling">enableScheduling</a></code> | <code>boolean</code> | Whether EventBridge Scheduler rules are enabled. |
1366
1373
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.failureDetection">failureDetection</a></code> | <code><a href="#ec2-instance-running-scheduler.FailureDetectionAlarms">FailureDetectionAlarms</a></code> | Optional CloudWatch alarms and log-based metrics for failure detection. |
1374
+ | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.logGroup">logGroup</a></code> | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerLogGroupProps">RunningSchedulerLogGroupProps</a></code> | CloudWatch Logs retention and removal policy for the function log group. |
1367
1375
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.resourceWait">resourceWait</a></code> | <code><a href="#ec2-instance-running-scheduler.ResourceWaitLimits">ResourceWaitLimits</a></code> | Per-instance wait limits for the running scheduler Lambda. |
1376
+ | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.runtime">runtime</a></code> | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerRuntimeProps">RunningSchedulerRuntimeProps</a></code> | Lambda memory, invoke timeout, and per-invocation instance concurrency. |
1368
1377
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.startSchedule">startSchedule</a></code> | <code><a href="#ec2-instance-running-scheduler.Schedule">Schedule</a></code> | Cron schedule for starting instances. |
1369
1378
  | <code><a href="#ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.stopSchedule">stopSchedule</a></code> | <code><a href="#ec2-instance-running-scheduler.Schedule">Schedule</a></code> | Cron schedule for stopping instances. |
1370
1379
 
@@ -1394,6 +1403,19 @@ Tag-based targeting for EC2 instances to start/stop.
1394
1403
 
1395
1404
  ---
1396
1405
 
1406
+ ##### `durable`<sup>Optional</sup> <a name="durable" id="ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.durable"></a>
1407
+
1408
+ ```typescript
1409
+ public readonly durable: RunningSchedulerDurableProps;
1410
+ ```
1411
+
1412
+ - *Type:* <a href="#ec2-instance-running-scheduler.RunningSchedulerDurableProps">RunningSchedulerDurableProps</a>
1413
+ - *Default:* executionTimeout 2 hours, retentionPeriod 1 day
1414
+
1415
+ Durable Execution timeout and history retention.
1416
+
1417
+ ---
1418
+
1397
1419
  ##### `enableScheduling`<sup>Optional</sup> <a name="enableScheduling" id="ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.enableScheduling"></a>
1398
1420
 
1399
1421
  ```typescript
@@ -1423,6 +1445,19 @@ Set `enabled: true` to create alarms; optionally pass `alarmTopic` for SNS notif
1423
1445
 
1424
1446
  ---
1425
1447
 
1448
+ ##### `logGroup`<sup>Optional</sup> <a name="logGroup" id="ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.logGroup"></a>
1449
+
1450
+ ```typescript
1451
+ public readonly logGroup: RunningSchedulerLogGroupProps;
1452
+ ```
1453
+
1454
+ - *Type:* <a href="#ec2-instance-running-scheduler.RunningSchedulerLogGroupProps">RunningSchedulerLogGroupProps</a>
1455
+ - *Default:* RetentionDays.THREE_MONTHS, RemovalPolicy.DESTROY
1456
+
1457
+ CloudWatch Logs retention and removal policy for the function log group.
1458
+
1459
+ ---
1460
+
1426
1461
  ##### `resourceWait`<sup>Optional</sup> <a name="resourceWait" id="ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.resourceWait"></a>
1427
1462
 
1428
1463
  ```typescript
@@ -1436,6 +1471,19 @@ Per-instance wait limits for the running scheduler Lambda.
1436
1471
 
1437
1472
  ---
1438
1473
 
1474
+ ##### `runtime`<sup>Optional</sup> <a name="runtime" id="ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.runtime"></a>
1475
+
1476
+ ```typescript
1477
+ public readonly runtime: RunningSchedulerRuntimeProps;
1478
+ ```
1479
+
1480
+ - *Type:* <a href="#ec2-instance-running-scheduler.RunningSchedulerRuntimeProps">RunningSchedulerRuntimeProps</a>
1481
+ - *Default:* 512 MB, 15 minutes, {@link DEFAULT_MAX_CONCURRENCY } (10)
1482
+
1483
+ Lambda memory, invoke timeout, and per-invocation instance concurrency.
1484
+
1485
+ ---
1486
+
1439
1487
  ##### `startSchedule`<sup>Optional</sup> <a name="startSchedule" id="ec2-instance-running-scheduler.EC2InstanceRunningSchedulerProps.property.startSchedule"></a>
1440
1488
 
1441
1489
  ```typescript
@@ -1464,7 +1512,9 @@ Cron schedule for stopping instances.
1464
1512
 
1465
1513
  Props for the EC2 instance running schedule CDK stack.
1466
1514
 
1467
- > [{@link EC2InstanceRunningSchedulerProps } for construct-level options not exposed here (e.g. `resourceWait`).]({@link EC2InstanceRunningSchedulerProps } for construct-level options not exposed here (e.g. `resourceWait`).)
1515
+ > [{@link EC2InstanceRunningSchedulerProps } for construct-level options not exposed here
1516
+ (e.g. `resourceWait`, `runtime`, `durable`, `logGroup`).]({@link EC2InstanceRunningSchedulerProps } for construct-level options not exposed here
1517
+ (e.g. `resourceWait`, `runtime`, `durable`, `logGroup`).)
1468
1518
 
1469
1519
  #### Initializer <a name="Initializer" id="ec2-instance-running-scheduler.EC2InstanceRunningScheduleStackProps.Initializer"></a>
1470
1520
 
@@ -1893,6 +1943,7 @@ const resourceWaitLimits: ResourceWaitLimits = { ... }
1893
1943
  | --- | --- | --- |
1894
1944
  | <code><a href="#ec2-instance-running-scheduler.ResourceWaitLimits.property.maxElapsedSeconds">maxElapsedSeconds</a></code> | <code>number</code> | Maximum wall-clock seconds spent waiting for a single instance to stabilize. |
1895
1945
  | <code><a href="#ec2-instance-running-scheduler.ResourceWaitLimits.property.maxLoopCount">maxLoopCount</a></code> | <code>number</code> | Maximum describe/wait loop iterations per instance. |
1946
+ | <code><a href="#ec2-instance-running-scheduler.ResourceWaitLimits.property.statusChangeWaitSeconds">statusChangeWaitSeconds</a></code> | <code>number</code> | Seconds to wait between describe iterations after start/stop or while transitioning. |
1896
1947
 
1897
1948
  ---
1898
1949
 
@@ -1922,6 +1973,70 @@ Maximum describe/wait loop iterations per instance.
1922
1973
 
1923
1974
  ---
1924
1975
 
1976
+ ##### `statusChangeWaitSeconds`<sup>Optional</sup> <a name="statusChangeWaitSeconds" id="ec2-instance-running-scheduler.ResourceWaitLimits.property.statusChangeWaitSeconds"></a>
1977
+
1978
+ ```typescript
1979
+ public readonly statusChangeWaitSeconds: number;
1980
+ ```
1981
+
1982
+ - *Type:* number
1983
+ - *Default:* {@link DEFAULT_RESOURCE_WAIT_LIMITS.statusChangeWaitSeconds } (20)
1984
+
1985
+ Seconds to wait between describe iterations after start/stop or while transitioning.
1986
+
1987
+ Lower values detect state changes sooner; higher values reduce DescribeInstances calls.
1988
+
1989
+ ---
1990
+
1991
+ ### RunningSchedulerDurableProps <a name="RunningSchedulerDurableProps" id="ec2-instance-running-scheduler.RunningSchedulerDurableProps"></a>
1992
+
1993
+ Durable Execution timeout and history retention for the running scheduler Lambda.
1994
+
1995
+ #### Initializer <a name="Initializer" id="ec2-instance-running-scheduler.RunningSchedulerDurableProps.Initializer"></a>
1996
+
1997
+ ```typescript
1998
+ import { RunningSchedulerDurableProps } from 'ec2-instance-running-scheduler'
1999
+
2000
+ const runningSchedulerDurableProps: RunningSchedulerDurableProps = { ... }
2001
+ ```
2002
+
2003
+ #### Properties <a name="Properties" id="Properties"></a>
2004
+
2005
+ | **Name** | **Type** | **Description** |
2006
+ | --- | --- | --- |
2007
+ | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerDurableProps.property.executionTimeout">executionTimeout</a></code> | <code>aws-cdk-lib.Duration</code> | Maximum duration of a durable execution. |
2008
+ | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerDurableProps.property.retentionPeriod">retentionPeriod</a></code> | <code>aws-cdk-lib.Duration</code> | How long to retain durable execution history. |
2009
+
2010
+ ---
2011
+
2012
+ ##### `executionTimeout`<sup>Optional</sup> <a name="executionTimeout" id="ec2-instance-running-scheduler.RunningSchedulerDurableProps.property.executionTimeout"></a>
2013
+
2014
+ ```typescript
2015
+ public readonly executionTimeout: Duration;
2016
+ ```
2017
+
2018
+ - *Type:* aws-cdk-lib.Duration
2019
+ - *Default:* Duration.hours(2)
2020
+
2021
+ Maximum duration of a durable execution.
2022
+
2023
+ Increase when many instances are processed with long per-instance waits.
2024
+
2025
+ ---
2026
+
2027
+ ##### `retentionPeriod`<sup>Optional</sup> <a name="retentionPeriod" id="ec2-instance-running-scheduler.RunningSchedulerDurableProps.property.retentionPeriod"></a>
2028
+
2029
+ ```typescript
2030
+ public readonly retentionPeriod: Duration;
2031
+ ```
2032
+
2033
+ - *Type:* aws-cdk-lib.Duration
2034
+ - *Default:* Duration.days(1)
2035
+
2036
+ How long to retain durable execution history.
2037
+
2038
+ ---
2039
+
1925
2040
  ### RunningSchedulerFailureDetectionProps <a name="RunningSchedulerFailureDetectionProps" id="ec2-instance-running-scheduler.RunningSchedulerFailureDetectionProps"></a>
1926
2041
 
1927
2042
  Props for {@link RunningSchedulerFailureDetection}.
@@ -1980,6 +2095,120 @@ Running scheduler Lambda to monitor.
1980
2095
 
1981
2096
  ---
1982
2097
 
2098
+ ### RunningSchedulerLogGroupProps <a name="RunningSchedulerLogGroupProps" id="ec2-instance-running-scheduler.RunningSchedulerLogGroupProps"></a>
2099
+
2100
+ CloudWatch Logs settings for the running scheduler function log group.
2101
+
2102
+ #### Initializer <a name="Initializer" id="ec2-instance-running-scheduler.RunningSchedulerLogGroupProps.Initializer"></a>
2103
+
2104
+ ```typescript
2105
+ import { RunningSchedulerLogGroupProps } from 'ec2-instance-running-scheduler'
2106
+
2107
+ const runningSchedulerLogGroupProps: RunningSchedulerLogGroupProps = { ... }
2108
+ ```
2109
+
2110
+ #### Properties <a name="Properties" id="Properties"></a>
2111
+
2112
+ | **Name** | **Type** | **Description** |
2113
+ | --- | --- | --- |
2114
+ | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerLogGroupProps.property.removalPolicy">removalPolicy</a></code> | <code>aws-cdk-lib.RemovalPolicy</code> | Removal policy for the log group. |
2115
+ | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerLogGroupProps.property.retention">retention</a></code> | <code>aws-cdk-lib.aws_logs.RetentionDays</code> | How long to retain application logs. |
2116
+
2117
+ ---
2118
+
2119
+ ##### `removalPolicy`<sup>Optional</sup> <a name="removalPolicy" id="ec2-instance-running-scheduler.RunningSchedulerLogGroupProps.property.removalPolicy"></a>
2120
+
2121
+ ```typescript
2122
+ public readonly removalPolicy: RemovalPolicy;
2123
+ ```
2124
+
2125
+ - *Type:* aws-cdk-lib.RemovalPolicy
2126
+ - *Default:* RemovalPolicy.DESTROY
2127
+
2128
+ Removal policy for the log group.
2129
+
2130
+ ---
2131
+
2132
+ ##### `retention`<sup>Optional</sup> <a name="retention" id="ec2-instance-running-scheduler.RunningSchedulerLogGroupProps.property.retention"></a>
2133
+
2134
+ ```typescript
2135
+ public readonly retention: RetentionDays;
2136
+ ```
2137
+
2138
+ - *Type:* aws-cdk-lib.aws_logs.RetentionDays
2139
+ - *Default:* RetentionDays.THREE_MONTHS
2140
+
2141
+ How long to retain application logs.
2142
+
2143
+ ---
2144
+
2145
+ ### RunningSchedulerRuntimeProps <a name="RunningSchedulerRuntimeProps" id="ec2-instance-running-scheduler.RunningSchedulerRuntimeProps"></a>
2146
+
2147
+ Lambda invoke settings and bounded parallelism for the running scheduler function.
2148
+
2149
+ Increase {@link memorySize} and {@link maxConcurrency} when a single invocation targets
2150
+ many instances or regions.
2151
+
2152
+ #### Initializer <a name="Initializer" id="ec2-instance-running-scheduler.RunningSchedulerRuntimeProps.Initializer"></a>
2153
+
2154
+ ```typescript
2155
+ import { RunningSchedulerRuntimeProps } from 'ec2-instance-running-scheduler'
2156
+
2157
+ const runningSchedulerRuntimeProps: RunningSchedulerRuntimeProps = { ... }
2158
+ ```
2159
+
2160
+ #### Properties <a name="Properties" id="Properties"></a>
2161
+
2162
+ | **Name** | **Type** | **Description** |
2163
+ | --- | --- | --- |
2164
+ | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerRuntimeProps.property.maxConcurrency">maxConcurrency</a></code> | <code>number</code> | Maximum number of instances processed in parallel by the durable `map`. |
2165
+ | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerRuntimeProps.property.memorySize">memorySize</a></code> | <code>number</code> | Memory allocated to the running scheduler Lambda, in MB. |
2166
+ | <code><a href="#ec2-instance-running-scheduler.RunningSchedulerRuntimeProps.property.timeout">timeout</a></code> | <code>aws-cdk-lib.Duration</code> | Invoke timeout for the Lambda function (not the durable execution timeout). |
2167
+
2168
+ ---
2169
+
2170
+ ##### `maxConcurrency`<sup>Optional</sup> <a name="maxConcurrency" id="ec2-instance-running-scheduler.RunningSchedulerRuntimeProps.property.maxConcurrency"></a>
2171
+
2172
+ ```typescript
2173
+ public readonly maxConcurrency: number;
2174
+ ```
2175
+
2176
+ - *Type:* number
2177
+ - *Default:* {@link DEFAULT_MAX_CONCURRENCY } (10)
2178
+
2179
+ Maximum number of instances processed in parallel by the durable `map`.
2180
+
2181
+ ---
2182
+
2183
+ ##### `memorySize`<sup>Optional</sup> <a name="memorySize" id="ec2-instance-running-scheduler.RunningSchedulerRuntimeProps.property.memorySize"></a>
2184
+
2185
+ ```typescript
2186
+ public readonly memorySize: number;
2187
+ ```
2188
+
2189
+ - *Type:* number
2190
+ - *Default:* 512
2191
+
2192
+ Memory allocated to the running scheduler Lambda, in MB.
2193
+
2194
+ ---
2195
+
2196
+ ##### `timeout`<sup>Optional</sup> <a name="timeout" id="ec2-instance-running-scheduler.RunningSchedulerRuntimeProps.property.timeout"></a>
2197
+
2198
+ ```typescript
2199
+ public readonly timeout: Duration;
2200
+ ```
2201
+
2202
+ - *Type:* aws-cdk-lib.Duration
2203
+ - *Default:* Duration.minutes(15)
2204
+
2205
+ Invoke timeout for the Lambda function (not the durable execution timeout).
2206
+
2207
+ AWS Lambda's maximum invoke timeout is 15 minutes. Durable waits can continue
2208
+ beyond this via {@link RunningSchedulerDurableProps.executionTimeout}.
2209
+
2210
+ ---
2211
+
1983
2212
  ### Schedule <a name="Schedule" id="ec2-instance-running-scheduler.Schedule"></a>
1984
2213
 
1985
2214
  Cron-style schedule configuration for start/stop actions.
@@ -2087,6 +2316,10 @@ Name of the Secrets Manager secret containing Slack token and channel.
2087
2316
 
2088
2317
  Defines which EC2 instances are targeted by tag key and values.
2089
2318
 
2319
+ Instances must already have this tag. IAM allows `ec2:StartInstances` /
2320
+ `ec2:StopInstances` only on instances in the stack account and region whose
2321
+ `aws:ResourceTag/<tagKey>` matches one of {@link TargetResource.tagValues}.
2322
+
2090
2323
  #### Initializer <a name="Initializer" id="ec2-instance-running-scheduler.TargetResource.Initializer"></a>
2091
2324
 
2092
2325
  ```typescript
package/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
  [![npm](https://img.shields.io/npm/v/ec2-instance-running-scheduler?style=flat-square)](https://www.npmjs.com/package/ec2-instance-running-scheduler)
5
5
  [![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/gammarers-aws-cdk-constructs/ec2-instance-running-scheduler/release.yml?branch=main&label=release&style=flat-square)](https://github.com/gammarers-aws-cdk-constructs/ec2-instance-running-scheduler/actions/workflows/release.yml)
6
6
  [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gammarers-aws-cdk-constructs/ec2-instance-running-scheduler?sort=semver&style=flat-square)](https://github.com/gammarers-aws-cdk-constructs/ec2-instance-running-scheduler/releases)
7
+
7
8
  [![View on Construct Hub](https://constructs.dev/badge?package=ec2-instance-running-scheduler)](https://constructs.dev/packages/ec2-instance-running-scheduler)
8
9
 
9
10
  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.
@@ -13,15 +14,17 @@ AWS CDK construct library that starts and stops EC2 instances on a cron schedule
13
14
  - **Tag-based targeting** – Select EC2 instances by tag key and values (e.g. `Schedule` / `YES`) via `tag:GetResources`.
14
15
  - **EventBridge Scheduler** – Separate cron rules for start and stop, with per-rule timezone (`aws-cdk-lib` `TimeZone`).
15
16
  - **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 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`).
17
+ - **Stable-state waiting** – After start/stop, the function waits (`resourceWait.statusChangeWaitSeconds`, default **20** seconds between attempts) and re-describes instances until `running` (start mode) or `stopped` (stop mode).
18
+ - **Configurable wait limits** – Per-instance **max loop count**, **max elapsed time**, and **status-change wait interval** via `resourceWait` (default: 90 loops / 1800 seconds / 20 seconds). Failures use explicit `ResourceWaitFailed:*` messages instead of running until the Durable execution timeout (construct default: 2 hours; override with `durable.executionTimeout`).
19
+ - **Configurable Lambda runtime** – Memory, invoke timeout, and bounded instance concurrency via `runtime` (default: **512 MB** / **15 minutes** / **maxConcurrency 10**). Durable execution timeout and history retention via `durable` (default: **2 hours** / **1 day**).
20
+ - **Configurable logs** – Log group retention and removal policy via `logGroup` (default: **3 months**, `RemovalPolicy.DESTROY`).
21
+ - **Validated environment variables** – The bundled handler parses env vars with **strict-env-resolver** (`StrictEnvResolver`). `SLACK_SECRET_NAME` is required; wait limits and `maxConcurrency` must be **positive integers** (`>= 1`).
19
22
  - **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
23
  - **Structured logging** – Durable execution **`ctx.logger`** for traceable JSON application logs (invocation, describe/start/stop/wait loops, wait limit errors, Slack steps, completion).
21
24
  - **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`).
22
25
  - **Scheduling toggle** – Enable or disable both schedules without removing the stack (`enableScheduling`).
23
26
  - **Configurable schedules** – Optional cron overrides for start and stop (`minute`, `hour`, `week`, `timezone`); sensible defaults if omitted.
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).
27
+ - **IAM and observability** – Start/stop is limited to EC2 instances in the stack account/region whose tags match `targetResource`. Slack secret read grant, **Parameters and Secrets Lambda Extension**, JSON logging, and a dedicated log group (override retention and removal policy via `logGroup`).
25
28
 
26
29
  ## Installation
27
30
 
@@ -50,6 +53,7 @@ Use the **construct** `EC2InstanceRunningScheduler` when embedding the scheduler
50
53
  ```typescript
51
54
  import * as cdk from 'aws-cdk-lib';
52
55
  import { TimeZone } from 'aws-cdk-lib';
56
+ import * as logs from 'aws-cdk-lib/aws-logs';
53
57
  import * as sns from 'aws-cdk-lib/aws-sns';
54
58
  import { EC2InstanceRunningScheduler } from 'ec2-instance-running-scheduler';
55
59
 
@@ -82,6 +86,20 @@ new EC2InstanceRunningScheduler(stack, 'EC2InstanceRunningScheduler', {
82
86
  resourceWait: {
83
87
  maxLoopCount: 120,
84
88
  maxElapsedSeconds: 3600,
89
+ statusChangeWaitSeconds: 15,
90
+ },
91
+ runtime: {
92
+ memorySize: 1024,
93
+ timeout: cdk.Duration.minutes(15),
94
+ maxConcurrency: 20,
95
+ },
96
+ durable: {
97
+ executionTimeout: cdk.Duration.hours(4),
98
+ retentionPeriod: cdk.Duration.days(7),
99
+ },
100
+ logGroup: {
101
+ retention: logs.RetentionDays.ONE_YEAR,
102
+ removalPolicy: cdk.RemovalPolicy.RETAIN,
85
103
  },
86
104
  failureDetection: {
87
105
  enabled: true,
@@ -90,7 +108,7 @@ new EC2InstanceRunningScheduler(stack, 'EC2InstanceRunningScheduler', {
90
108
  });
91
109
  ```
92
110
 
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.
111
+ 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`**, **`runtime`**, **`durable`**, and **`logGroup`**, use the construct directly or extend the stack in your app.
94
112
 
95
113
  ```typescript
96
114
  import * as cdk from 'aws-cdk-lib';
@@ -134,6 +152,27 @@ new EC2InstanceRunningScheduleStack(app, 'EC2InstanceRunningScheduleStack', {
134
152
  });
135
153
  ```
136
154
 
155
+ ## Tag instances before scheduling
156
+
157
+ The scheduler only starts and stops EC2 instances that **already** have the tag key and one of the tag values in `targetResource`. Tag instances in the same account and region as the stack **before** enabling schedules.
158
+
159
+ **AWS CLI**
160
+
161
+ ```bash
162
+ aws ec2 create-tags \
163
+ --resources i-0123456789abcdef0 \
164
+ --tags Key=Schedule,Value=YES
165
+ ```
166
+
167
+ **Console** – EC2 → Instances → select the instance → Tags → Add `Schedule` = `YES` (or your `tagKey` / `tagValues`).
168
+
169
+ IAM for `ec2:StartInstances` and `ec2:StopInstances` is limited to:
170
+
171
+ - instance ARNs in the stack **account** and **region** (`arn:...:ec2:<region>:<account>:instance/*`)
172
+ - instances whose `aws:ResourceTag/<tagKey>` matches one of `tagValues`
173
+
174
+ An instance without the tag is not discovered by `tag:GetResources`, and start/stop is denied even if an instance ID is known. `tag:GetResources` and `ec2:DescribeInstances` still use `Resource: *` because those APIs do not support resource-level permissions or resource-tag conditions.
175
+
137
176
  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:
138
177
 
139
178
  | Variable | Source | Purpose |
@@ -141,8 +180,10 @@ EventBridge Scheduler invokes the Lambda with `Params.TagKey`, `Params.TagValues
141
180
  | `SLACK_SECRET_NAME` | `secrets.slackSecretName` | Secrets Manager secret for Slack (required) |
142
181
  | `PROCESS_RESOURCE_MAX_LOOP_COUNT` | `resourceWait.maxLoopCount` (default `90`) | Max describe/wait iterations per instance |
143
182
  | `PROCESS_RESOURCE_MAX_ELAPSED_SECONDS` | `resourceWait.maxElapsedSeconds` (default `1800`) | Max wall-clock seconds waiting for one instance |
183
+ | `PROCESS_RESOURCE_STATUS_CHANGE_WAIT_SECONDS` | `resourceWait.statusChangeWaitSeconds` (default `20`) | Seconds between describe/wait iterations |
184
+ | `PROCESS_RESOURCES_MAX_CONCURRENCY` | `runtime.maxConcurrency` (default `10`) | Max instances processed in parallel |
144
185
 
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.
186
+ When you set wait limits via `resourceWait` or concurrency via `runtime.maxConcurrency`, the construct writes them as decimal integer strings. At invocation the handler parses them with **strict-env-resolver**; each value must be a **positive integer** (`>= 1`). Missing `SLACK_SECRET_NAME` or invalid env values cause `StrictEnvValidationError` at the start of an invocation.
146
187
 
147
188
  ## Options
148
189
 
@@ -156,16 +197,21 @@ When you set wait limits via `resourceWait`, the construct writes them as decima
156
197
  | `stopSchedule` | `Schedule` | No | Cron for stopping instances (default: `5 19 ? * MON-FRI *` in `Etc/UTC`). |
157
198
  | `enableScheduling` | `boolean` | No | Whether both scheduler rules are enabled (default: `true`). |
158
199
  | `resourceWait` | `ResourceWaitLimits` | No | Per-instance wait caps (see below). |
200
+ | `runtime` | `RunningSchedulerRuntimeProps` | No | Lambda memory, invoke timeout, and map concurrency. |
201
+ | `durable` | `RunningSchedulerDurableProps` | No | Durable execution timeout and history retention. |
202
+ | `logGroup` | `RunningSchedulerLogGroupProps` | No | Function log group retention and removal policy. |
159
203
  | `failureDetection` | `FailureDetectionAlarms` | No | Optional CloudWatch alarms and log-based metrics (see below). |
160
204
 
161
205
  ### EC2InstanceRunningScheduleStack
162
206
 
163
- Includes `targetResource`, `secrets`, `startSchedule`, `stopSchedule`, `enableScheduling`, `failureDetection`, and standard `StackProps`. Does **not** expose `resourceWait`; use `EC2InstanceRunningScheduler` when you need custom wait limits.
207
+ Includes `targetResource`, `secrets`, `startSchedule`, `stopSchedule`, `enableScheduling`, `failureDetection`, and standard `StackProps`. Does **not** expose `resourceWait`, `runtime`, `durable`, or `logGroup`; use `EC2InstanceRunningScheduler` when you need custom wait, Lambda, Durable, or log settings.
164
208
 
165
209
  ### TargetResource
166
210
 
167
- - `tagKey` – Tag key used to select instances (e.g. `Schedule`).
168
- - `tagValues` – Tag values that must match (e.g. `['YES']`).
211
+ - `tagKey` – Tag key used to select instances (e.g. `Schedule`). Required on each target instance before schedules run.
212
+ - `tagValues` – Tag values that must match (e.g. `['YES']`). At least one value is required.
213
+
214
+ See [Tag instances before scheduling](#tag-instances-before-scheduling).
169
215
 
170
216
  ### Schedule
171
217
 
@@ -180,13 +226,32 @@ Includes `targetResource`, `secrets`, `startSchedule`, `stopSchedule`, `enableSc
180
226
 
181
227
  ### ResourceWaitLimits
182
228
 
183
- Written to `PROCESS_RESOURCE_MAX_LOOP_COUNT` and `PROCESS_RESOURCE_MAX_ELAPSED_SECONDS` on the running scheduler Lambda.
229
+ Written to `PROCESS_RESOURCE_MAX_LOOP_COUNT`, `PROCESS_RESOURCE_MAX_ELAPSED_SECONDS`, and `PROCESS_RESOURCE_STATUS_CHANGE_WAIT_SECONDS` on the running scheduler Lambda.
184
230
 
185
231
  - `maxLoopCount` – Maximum describe/wait loop iterations per instance (default: **90**). Must be a positive integer when set.
186
232
  - `maxElapsedSeconds` – Maximum wall-clock seconds spent waiting for one instance to stabilize (default: **1800**, 30 minutes). Must be a positive integer when set.
233
+ - `statusChangeWaitSeconds` – Seconds between describe iterations after start/stop or while transitioning (default: **20**). Must be a positive integer when set.
187
234
 
188
235
  When a limit is exceeded during waiting, the handler throws an error with prefix `ResourceWaitFailed:` (`MaxLoopCountExceeded`, `MaxElapsedTimeExceeded`, or `UnexpectedInstanceState` for unknown EC2 states).
189
236
 
237
+ ### RunningSchedulerRuntimeProps
238
+
239
+ Lambda invoke settings. Written `maxConcurrency` to `PROCESS_RESOURCES_MAX_CONCURRENCY`.
240
+
241
+ - `memorySize` – Memory in MB (default: **512**). Must be a positive integer when set.
242
+ - `timeout` – Lambda invoke timeout (default: **15 minutes**). AWS maximum is 15 minutes; durable waits continue under `durable.executionTimeout`.
243
+ - `maxConcurrency` – Max instances processed in parallel (default: **10**). Must be a positive integer when set. Increase with instance count.
244
+
245
+ ### RunningSchedulerDurableProps
246
+
247
+ - `executionTimeout` – Maximum durable execution duration (default: **2 hours**). Increase when many instances wait in sequence of batches.
248
+ - `retentionPeriod` – Durable execution history retention (default: **1 day**).
249
+
250
+ ### RunningSchedulerLogGroupProps
251
+
252
+ - `retention` – CloudWatch Logs retention (default: **`RetentionDays.THREE_MONTHS`**).
253
+ - `removalPolicy` – Log group removal policy (default: **`RemovalPolicy.DESTROY`**).
254
+
190
255
  ### FailureDetectionAlarms
191
256
 
192
257
  Optional operational failure detection. Alarms are created only when `enabled` is `true`.
@@ -209,7 +274,7 @@ Custom metrics are published under the `EC2InstanceRunningScheduler` namespace.
209
274
 
210
275
  - **Node.js** ≥ 20.0.0 (for developing or synthesizing CDK apps that depend on this package).
211
276
  - **aws-cdk-lib** ^2.232.0 and **constructs** ^10.5.1 (peer dependencies).
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.
277
+ - **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.7) and parses env vars via **strict-env-resolver** (^0.6). 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.
213
278
 
214
279
  ## License
215
280