rds-database-auto-start-preventer 0.2.6 → 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 +6 -6
- package/README.md +3 -3
- package/assets/funcs/auto-start-prevent.lambda/index.js +720 -219
- package/assets/funcs/auto-start-prevent.lambda/index.js.map +4 -4
- package/lib/constructs/rds-database-auto-start-preventer.d.ts +2 -1
- package/lib/constructs/rds-database-auto-start-preventer.js +5 -3
- package/lib/funcs/auto-start-prevent.lambda.d.ts +7 -4
- package/lib/funcs/auto-start-prevent.lambda.js +45 -169
- package/lib/funcs/auto-start-prevent.predicates.d.ts +251 -0
- package/lib/funcs/auto-start-prevent.predicates.js +253 -0
- package/lib/stacks/rds-database-auto-start-prevent-stack.js +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for the RDS auto-start prevent Lambda.
|
|
3
|
+
* No AWS SDK, Durable context, env, or clock dependencies.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Detail payload of an RDS auto-start event from EventBridge.
|
|
7
|
+
*/
|
|
8
|
+
export interface RdsAutoStartDetail {
|
|
9
|
+
/** Event ID: RDS-EVENT-0154 (DB instance) or RDS-EVENT-0153 (DB cluster). */
|
|
10
|
+
EventID: 'RDS-EVENT-0154' | 'RDS-EVENT-0153';
|
|
11
|
+
/** Resource type that emitted the event. */
|
|
12
|
+
SourceType: 'DB_INSTANCE' | 'CLUSTER';
|
|
13
|
+
/** ARN of the DB instance or cluster. */
|
|
14
|
+
SourceArn: string;
|
|
15
|
+
/** DB instance or cluster identifier from the event. */
|
|
16
|
+
SourceIdentifier: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* RDS auto-start event as received from EventBridge.
|
|
20
|
+
*/
|
|
21
|
+
export interface RdsAutoStartEvent {
|
|
22
|
+
'detail-type': 'RDS DB Instance Event' | 'RDS DB Cluster Event';
|
|
23
|
+
'source': 'aws.rds';
|
|
24
|
+
'detail': RdsAutoStartDetail;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Tag-based filter parameters for the handler.
|
|
28
|
+
*/
|
|
29
|
+
export interface AutoStartParams {
|
|
30
|
+
/** Tag key to match on the resource. */
|
|
31
|
+
tagKey: string;
|
|
32
|
+
/** Allowed tag values; the resource is processed only when its tag value is in this list. */
|
|
33
|
+
tagValues: string[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Slack credentials stored in Secrets Manager.
|
|
37
|
+
*/
|
|
38
|
+
export interface SlackSecret {
|
|
39
|
+
/** Slack bot or user OAuth token. */
|
|
40
|
+
token: string;
|
|
41
|
+
/** Channel ID or name to post notifications to. */
|
|
42
|
+
channel: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Normalized handler input: EventBridge event and tag filter parameters.
|
|
46
|
+
*/
|
|
47
|
+
export interface AutoStartPreventInput {
|
|
48
|
+
event: RdsAutoStartEvent;
|
|
49
|
+
params: AutoStartParams;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Handler result when no stop action was taken.
|
|
53
|
+
*/
|
|
54
|
+
export interface NoOpResult {
|
|
55
|
+
action: 'no-op';
|
|
56
|
+
reason: 'tag not matched or not found' | 'already stopped';
|
|
57
|
+
status: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Handler result when this invocation called StopDB* and the resource reached `stopped`.
|
|
61
|
+
*/
|
|
62
|
+
export interface StoppedResult {
|
|
63
|
+
action: 'stopped';
|
|
64
|
+
finalStatus: string;
|
|
65
|
+
account: string;
|
|
66
|
+
region: string;
|
|
67
|
+
identifier: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* AWS-style tag (Key/Value).
|
|
71
|
+
*/
|
|
72
|
+
export interface Tag {
|
|
73
|
+
Key?: string;
|
|
74
|
+
Value?: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* State snapshot while waiting on RDS describe APIs.
|
|
78
|
+
*/
|
|
79
|
+
export interface WaitState {
|
|
80
|
+
/** Current DB instance or cluster status. */
|
|
81
|
+
status: string;
|
|
82
|
+
/** DB instance or cluster identifier. */
|
|
83
|
+
identifier: string;
|
|
84
|
+
/** Tags from the describe response; present on the first wait check only. */
|
|
85
|
+
tags?: Tag[];
|
|
86
|
+
}
|
|
87
|
+
/** Continue waiting with a delay. */
|
|
88
|
+
export interface ContinueWait {
|
|
89
|
+
shouldContinue: true;
|
|
90
|
+
delay: {
|
|
91
|
+
minutes: number;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Stop waiting. */
|
|
95
|
+
export interface StopWait {
|
|
96
|
+
shouldContinue: false;
|
|
97
|
+
}
|
|
98
|
+
/** Result of a durable waitStrategy. */
|
|
99
|
+
export type WaitStrategyResult = ContinueWait | StopWait;
|
|
100
|
+
/**
|
|
101
|
+
* RDS statuses that indicate an in-progress transition.
|
|
102
|
+
* The handler waits every 5 minutes while the resource remains in one of these states.
|
|
103
|
+
*/
|
|
104
|
+
export declare const TRANSITIONAL_STATUSES: Set<string>;
|
|
105
|
+
/**
|
|
106
|
+
* Returns true when the status is transitional and waiting should continue.
|
|
107
|
+
*
|
|
108
|
+
* @param status - Current DB instance or cluster status.
|
|
109
|
+
* @returns Whether the status is transitional.
|
|
110
|
+
*/
|
|
111
|
+
export declare const isTransitionalStatus: (status: string) => boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Type guard for Slack credentials returned by `secretFetcher.getSecretValue`.
|
|
114
|
+
*
|
|
115
|
+
* aws-lambda-secret-fetcher ^0.7 parses SecretString with quiet-json-parser and
|
|
116
|
+
* falls back to the raw string on invalid JSON, so callers must validate shape.
|
|
117
|
+
*
|
|
118
|
+
* @param value - Value returned from the secret fetcher.
|
|
119
|
+
* @returns Whether value is a SlackSecret with non-empty token and channel.
|
|
120
|
+
*/
|
|
121
|
+
export declare const isSlackSecret: (value: unknown) => value is SlackSecret;
|
|
122
|
+
/**
|
|
123
|
+
* Type guard: input is `{ event, params }` as produced by the EventBridge target.
|
|
124
|
+
*
|
|
125
|
+
* @param input - Raw Lambda invocation payload.
|
|
126
|
+
* @returns Whether input has non-null event and params.
|
|
127
|
+
*/
|
|
128
|
+
export declare const isAutoStartPreventInput: (input: unknown) => input is AutoStartPreventInput;
|
|
129
|
+
/**
|
|
130
|
+
* Normalizes invocation input to {@link AutoStartPreventInput}.
|
|
131
|
+
*
|
|
132
|
+
* @param input - `{ event, params }` from EventBridge InputTransformer (or the same shape on direct Invoke).
|
|
133
|
+
* @returns Event plus tag filter parameters.
|
|
134
|
+
* @throws When the payload is not `{ event, params }`.
|
|
135
|
+
*/
|
|
136
|
+
export declare const normalizeInput: (input: unknown) => AutoStartPreventInput;
|
|
137
|
+
/**
|
|
138
|
+
* Returns true if the resource has a tag with the given key and a value in the allowed list.
|
|
139
|
+
*
|
|
140
|
+
* @param params - Tag key and allowed values.
|
|
141
|
+
* @param tags - Resource tag list (e.g. from DescribeDBInstances / DescribeDBClusters).
|
|
142
|
+
* @returns Whether the tag matches.
|
|
143
|
+
*/
|
|
144
|
+
export declare const matchTag: (params: AutoStartParams, tags?: Tag[]) => boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Whether the EventBridge detail identifies a supported DB instance auto-start event.
|
|
147
|
+
*
|
|
148
|
+
* @param detailType - EventBridge detail-type.
|
|
149
|
+
* @param detail - RDS event detail.
|
|
150
|
+
* @returns True for RDS-EVENT-0154 on a DB instance.
|
|
151
|
+
*/
|
|
152
|
+
export declare const isDbInstanceAutoStart: (detailType: RdsAutoStartEvent["detail-type"], detail: RdsAutoStartDetail) => boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether the EventBridge detail identifies a supported DB cluster auto-start event.
|
|
155
|
+
*
|
|
156
|
+
* @param detailType - EventBridge detail-type.
|
|
157
|
+
* @param detail - RDS event detail.
|
|
158
|
+
* @returns True for RDS-EVENT-0153 on a cluster.
|
|
159
|
+
*/
|
|
160
|
+
export declare const isDbClusterAutoStart: (detailType: RdsAutoStartEvent["detail-type"], detail: RdsAutoStartDetail) => boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Wait strategy while describing until the resource leaves transitional statuses.
|
|
163
|
+
*
|
|
164
|
+
* @param state - Latest wait state.
|
|
165
|
+
* @returns Continue every 5 minutes while transitional; otherwise stop.
|
|
166
|
+
*/
|
|
167
|
+
export declare const waitStrategyUntilStable: (state: WaitState) => WaitStrategyResult;
|
|
168
|
+
/**
|
|
169
|
+
* Wait strategy after StopDB* until the resource reaches `stopped`.
|
|
170
|
+
*
|
|
171
|
+
* @param state - Latest wait state.
|
|
172
|
+
* @returns Stop when `stopped`; continue while transitional.
|
|
173
|
+
* @throws When the status is neither stopped nor transitional.
|
|
174
|
+
*/
|
|
175
|
+
export declare const waitStrategyUntilStopped: (state: WaitState) => WaitStrategyResult;
|
|
176
|
+
/**
|
|
177
|
+
* Decision after the first describe and a successful tag match.
|
|
178
|
+
*/
|
|
179
|
+
export type AfterTagMatchDecision = {
|
|
180
|
+
kind: 'stop';
|
|
181
|
+
} | {
|
|
182
|
+
kind: 'no-op';
|
|
183
|
+
result: NoOpResult;
|
|
184
|
+
} | {
|
|
185
|
+
kind: 'error';
|
|
186
|
+
message: string;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Decides the next action when tags matched and StopDB* has not been called yet.
|
|
190
|
+
*
|
|
191
|
+
* @param status - Status from the first describe after leaving transitional states.
|
|
192
|
+
* @returns Stop when `available`; no-op when already `stopped`; otherwise error.
|
|
193
|
+
*/
|
|
194
|
+
export declare const decideAfterTagMatch: (status: string) => AfterTagMatchDecision;
|
|
195
|
+
/**
|
|
196
|
+
* Builds the no-op result used when tags do not match.
|
|
197
|
+
*
|
|
198
|
+
* @param status - Current resource status.
|
|
199
|
+
* @returns No-op result with tag mismatch reason.
|
|
200
|
+
*/
|
|
201
|
+
export declare const tagMismatchNoOp: (status: string) => NoOpResult;
|
|
202
|
+
/**
|
|
203
|
+
* Parses region and account from an RDS resource ARN (`arn:aws:rds:region:account:...`).
|
|
204
|
+
*
|
|
205
|
+
* @param sourceArn - SourceArn from the RDS event detail.
|
|
206
|
+
* @returns Region and account id segments.
|
|
207
|
+
*/
|
|
208
|
+
export declare const parseRdsSourceArn: (sourceArn: string) => {
|
|
209
|
+
region: string;
|
|
210
|
+
account: string;
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* Arguments for the Slack stop-success notification.
|
|
214
|
+
*/
|
|
215
|
+
export interface SlackStopNotificationArgs {
|
|
216
|
+
channel: string;
|
|
217
|
+
sourceType: RdsAutoStartDetail['SourceType'];
|
|
218
|
+
sourceIdentifier: string;
|
|
219
|
+
account: string;
|
|
220
|
+
region: string;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Builds the Slack `chat.postMessage` payload after a successful stop.
|
|
224
|
+
*
|
|
225
|
+
* @param args - Channel and resource identity fields.
|
|
226
|
+
* @returns Arguments suitable for `WebClient.chat.postMessage`.
|
|
227
|
+
*/
|
|
228
|
+
export declare const buildSlackStopNotification: (args: SlackStopNotificationArgs) => {
|
|
229
|
+
channel: string;
|
|
230
|
+
attachments: {
|
|
231
|
+
color: string;
|
|
232
|
+
pretext: string;
|
|
233
|
+
fields: {
|
|
234
|
+
title: string;
|
|
235
|
+
value: string;
|
|
236
|
+
short: boolean;
|
|
237
|
+
}[];
|
|
238
|
+
}[];
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
241
|
+
* Builds the success result after StopDB* reached `stopped`.
|
|
242
|
+
*
|
|
243
|
+
* @param args - Final status and identity fields.
|
|
244
|
+
* @returns StoppedResult for the handler return value.
|
|
245
|
+
*/
|
|
246
|
+
export declare const buildStoppedResult: (args: {
|
|
247
|
+
finalStatus: string;
|
|
248
|
+
account: string;
|
|
249
|
+
region: string;
|
|
250
|
+
identifier: string;
|
|
251
|
+
}) => StoppedResult;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pure helpers for the RDS auto-start prevent Lambda.
|
|
4
|
+
* No AWS SDK, Durable context, env, or clock dependencies.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.buildStoppedResult = exports.buildSlackStopNotification = exports.parseRdsSourceArn = exports.tagMismatchNoOp = exports.decideAfterTagMatch = exports.waitStrategyUntilStopped = exports.waitStrategyUntilStable = exports.isDbClusterAutoStart = exports.isDbInstanceAutoStart = exports.matchTag = exports.normalizeInput = exports.isAutoStartPreventInput = exports.isSlackSecret = exports.isTransitionalStatus = exports.TRANSITIONAL_STATUSES = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* RDS statuses that indicate an in-progress transition.
|
|
10
|
+
* The handler waits every 5 minutes while the resource remains in one of these states.
|
|
11
|
+
*/
|
|
12
|
+
exports.TRANSITIONAL_STATUSES = new Set([
|
|
13
|
+
'starting',
|
|
14
|
+
'configuring-enhanced-monitoring',
|
|
15
|
+
'backing-up',
|
|
16
|
+
'modifying',
|
|
17
|
+
'stopping',
|
|
18
|
+
]);
|
|
19
|
+
/**
|
|
20
|
+
* Returns true when the status is transitional and waiting should continue.
|
|
21
|
+
*
|
|
22
|
+
* @param status - Current DB instance or cluster status.
|
|
23
|
+
* @returns Whether the status is transitional.
|
|
24
|
+
*/
|
|
25
|
+
const isTransitionalStatus = (status) => exports.TRANSITIONAL_STATUSES.has(status);
|
|
26
|
+
exports.isTransitionalStatus = isTransitionalStatus;
|
|
27
|
+
/**
|
|
28
|
+
* Type guard for Slack credentials returned by `secretFetcher.getSecretValue`.
|
|
29
|
+
*
|
|
30
|
+
* aws-lambda-secret-fetcher ^0.7 parses SecretString with quiet-json-parser and
|
|
31
|
+
* falls back to the raw string on invalid JSON, so callers must validate shape.
|
|
32
|
+
*
|
|
33
|
+
* @param value - Value returned from the secret fetcher.
|
|
34
|
+
* @returns Whether value is a SlackSecret with non-empty token and channel.
|
|
35
|
+
*/
|
|
36
|
+
const isSlackSecret = (value) => {
|
|
37
|
+
if (typeof value !== 'object' || value == null) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (!('token' in value) || !('channel' in value)) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return typeof value.token === 'string' &&
|
|
44
|
+
value.token.length > 0 &&
|
|
45
|
+
typeof value.channel === 'string' &&
|
|
46
|
+
value.channel.length > 0;
|
|
47
|
+
};
|
|
48
|
+
exports.isSlackSecret = isSlackSecret;
|
|
49
|
+
/**
|
|
50
|
+
* Type guard: input is `{ event, params }` as produced by the EventBridge target.
|
|
51
|
+
*
|
|
52
|
+
* @param input - Raw Lambda invocation payload.
|
|
53
|
+
* @returns Whether input has non-null event and params.
|
|
54
|
+
*/
|
|
55
|
+
const isAutoStartPreventInput = (input) => {
|
|
56
|
+
if (typeof input !== 'object' || input == null) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (!('event' in input) || !('params' in input)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return input.event != null && input.params != null;
|
|
63
|
+
};
|
|
64
|
+
exports.isAutoStartPreventInput = isAutoStartPreventInput;
|
|
65
|
+
/**
|
|
66
|
+
* Normalizes invocation input to {@link AutoStartPreventInput}.
|
|
67
|
+
*
|
|
68
|
+
* @param input - `{ event, params }` from EventBridge InputTransformer (or the same shape on direct Invoke).
|
|
69
|
+
* @returns Event plus tag filter parameters.
|
|
70
|
+
* @throws When the payload is not `{ event, params }`.
|
|
71
|
+
*/
|
|
72
|
+
const normalizeInput = (input) => {
|
|
73
|
+
if ((0, exports.isAutoStartPreventInput)(input)) {
|
|
74
|
+
return input;
|
|
75
|
+
}
|
|
76
|
+
throw new Error('Invalid input: expected { event, params }.');
|
|
77
|
+
};
|
|
78
|
+
exports.normalizeInput = normalizeInput;
|
|
79
|
+
/**
|
|
80
|
+
* Returns true if the resource has a tag with the given key and a value in the allowed list.
|
|
81
|
+
*
|
|
82
|
+
* @param params - Tag key and allowed values.
|
|
83
|
+
* @param tags - Resource tag list (e.g. from DescribeDBInstances / DescribeDBClusters).
|
|
84
|
+
* @returns Whether the tag matches.
|
|
85
|
+
*/
|
|
86
|
+
const matchTag = (params, tags) => {
|
|
87
|
+
if (!tags || tags.length === 0) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const value = tags.find(t => t.Key === params.tagKey)?.Value;
|
|
91
|
+
if (!value) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return params.tagValues.includes(value);
|
|
95
|
+
};
|
|
96
|
+
exports.matchTag = matchTag;
|
|
97
|
+
/**
|
|
98
|
+
* Whether the EventBridge detail identifies a supported DB instance auto-start event.
|
|
99
|
+
*
|
|
100
|
+
* @param detailType - EventBridge detail-type.
|
|
101
|
+
* @param detail - RDS event detail.
|
|
102
|
+
* @returns True for RDS-EVENT-0154 on a DB instance.
|
|
103
|
+
*/
|
|
104
|
+
const isDbInstanceAutoStart = (detailType, detail) => detailType === 'RDS DB Instance Event' &&
|
|
105
|
+
detail.SourceType === 'DB_INSTANCE' &&
|
|
106
|
+
detail.EventID === 'RDS-EVENT-0154';
|
|
107
|
+
exports.isDbInstanceAutoStart = isDbInstanceAutoStart;
|
|
108
|
+
/**
|
|
109
|
+
* Whether the EventBridge detail identifies a supported DB cluster auto-start event.
|
|
110
|
+
*
|
|
111
|
+
* @param detailType - EventBridge detail-type.
|
|
112
|
+
* @param detail - RDS event detail.
|
|
113
|
+
* @returns True for RDS-EVENT-0153 on a cluster.
|
|
114
|
+
*/
|
|
115
|
+
const isDbClusterAutoStart = (detailType, detail) => detailType === 'RDS DB Cluster Event' &&
|
|
116
|
+
detail.SourceType === 'CLUSTER' &&
|
|
117
|
+
detail.EventID === 'RDS-EVENT-0153';
|
|
118
|
+
exports.isDbClusterAutoStart = isDbClusterAutoStart;
|
|
119
|
+
/**
|
|
120
|
+
* Wait strategy while describing until the resource leaves transitional statuses.
|
|
121
|
+
*
|
|
122
|
+
* @param state - Latest wait state.
|
|
123
|
+
* @returns Continue every 5 minutes while transitional; otherwise stop.
|
|
124
|
+
*/
|
|
125
|
+
const waitStrategyUntilStable = (state) => {
|
|
126
|
+
if ((0, exports.isTransitionalStatus)(state.status)) {
|
|
127
|
+
return { shouldContinue: true, delay: { minutes: 5 } };
|
|
128
|
+
}
|
|
129
|
+
return { shouldContinue: false };
|
|
130
|
+
};
|
|
131
|
+
exports.waitStrategyUntilStable = waitStrategyUntilStable;
|
|
132
|
+
/**
|
|
133
|
+
* Wait strategy after StopDB* until the resource reaches `stopped`.
|
|
134
|
+
*
|
|
135
|
+
* @param state - Latest wait state.
|
|
136
|
+
* @returns Stop when `stopped`; continue while transitional.
|
|
137
|
+
* @throws When the status is neither stopped nor transitional.
|
|
138
|
+
*/
|
|
139
|
+
const waitStrategyUntilStopped = (state) => {
|
|
140
|
+
if (state.status === 'stopped') {
|
|
141
|
+
return { shouldContinue: false };
|
|
142
|
+
}
|
|
143
|
+
if ((0, exports.isTransitionalStatus)(state.status)) {
|
|
144
|
+
return { shouldContinue: true, delay: { minutes: 5 } };
|
|
145
|
+
}
|
|
146
|
+
throw new Error(`Unexpected status while waiting for stop: ${state.status}`);
|
|
147
|
+
};
|
|
148
|
+
exports.waitStrategyUntilStopped = waitStrategyUntilStopped;
|
|
149
|
+
/**
|
|
150
|
+
* Decides the next action when tags matched and StopDB* has not been called yet.
|
|
151
|
+
*
|
|
152
|
+
* @param status - Status from the first describe after leaving transitional states.
|
|
153
|
+
* @returns Stop when `available`; no-op when already `stopped`; otherwise error.
|
|
154
|
+
*/
|
|
155
|
+
const decideAfterTagMatch = (status) => {
|
|
156
|
+
if (status === 'available') {
|
|
157
|
+
return { kind: 'stop' };
|
|
158
|
+
}
|
|
159
|
+
if (status === 'stopped') {
|
|
160
|
+
return {
|
|
161
|
+
kind: 'no-op',
|
|
162
|
+
result: {
|
|
163
|
+
action: 'no-op',
|
|
164
|
+
reason: 'already stopped',
|
|
165
|
+
status,
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
kind: 'error',
|
|
171
|
+
message: `DB status is not stopped after processing: ${status}`,
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
exports.decideAfterTagMatch = decideAfterTagMatch;
|
|
175
|
+
/**
|
|
176
|
+
* Builds the no-op result used when tags do not match.
|
|
177
|
+
*
|
|
178
|
+
* @param status - Current resource status.
|
|
179
|
+
* @returns No-op result with tag mismatch reason.
|
|
180
|
+
*/
|
|
181
|
+
const tagMismatchNoOp = (status) => ({
|
|
182
|
+
action: 'no-op',
|
|
183
|
+
reason: 'tag not matched or not found',
|
|
184
|
+
status,
|
|
185
|
+
});
|
|
186
|
+
exports.tagMismatchNoOp = tagMismatchNoOp;
|
|
187
|
+
/**
|
|
188
|
+
* Parses region and account from an RDS resource ARN (`arn:aws:rds:region:account:...`).
|
|
189
|
+
*
|
|
190
|
+
* @param sourceArn - SourceArn from the RDS event detail.
|
|
191
|
+
* @returns Region and account id segments.
|
|
192
|
+
*/
|
|
193
|
+
const parseRdsSourceArn = (sourceArn) => {
|
|
194
|
+
const parts = sourceArn.split(':');
|
|
195
|
+
return {
|
|
196
|
+
region: parts[3] ?? '',
|
|
197
|
+
account: parts[4] ?? '',
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
exports.parseRdsSourceArn = parseRdsSourceArn;
|
|
201
|
+
/**
|
|
202
|
+
* Builds the Slack `chat.postMessage` payload after a successful stop.
|
|
203
|
+
*
|
|
204
|
+
* @param args - Channel and resource identity fields.
|
|
205
|
+
* @returns Arguments suitable for `WebClient.chat.postMessage`.
|
|
206
|
+
*/
|
|
207
|
+
const buildSlackStopNotification = (args) => ({
|
|
208
|
+
channel: args.channel,
|
|
209
|
+
attachments: [
|
|
210
|
+
{
|
|
211
|
+
color: '#36a64f',
|
|
212
|
+
pretext: `😴 Successfully stopped the automatically running RDS ${args.sourceType} ${args.sourceIdentifier}.`,
|
|
213
|
+
fields: [
|
|
214
|
+
{
|
|
215
|
+
title: 'Account',
|
|
216
|
+
value: args.account,
|
|
217
|
+
short: true,
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
title: 'Region',
|
|
221
|
+
value: args.region,
|
|
222
|
+
short: true,
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
title: 'Type',
|
|
226
|
+
value: args.sourceType,
|
|
227
|
+
short: true,
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
title: 'Identifier',
|
|
231
|
+
value: args.sourceIdentifier,
|
|
232
|
+
short: true,
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
});
|
|
238
|
+
exports.buildSlackStopNotification = buildSlackStopNotification;
|
|
239
|
+
/**
|
|
240
|
+
* Builds the success result after StopDB* reached `stopped`.
|
|
241
|
+
*
|
|
242
|
+
* @param args - Final status and identity fields.
|
|
243
|
+
* @returns StoppedResult for the handler return value.
|
|
244
|
+
*/
|
|
245
|
+
const buildStoppedResult = (args) => ({
|
|
246
|
+
action: 'stopped',
|
|
247
|
+
finalStatus: args.finalStatus,
|
|
248
|
+
account: args.account,
|
|
249
|
+
region: args.region,
|
|
250
|
+
identifier: args.identifier,
|
|
251
|
+
});
|
|
252
|
+
exports.buildStoppedResult = buildStoppedResult;
|
|
253
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0by1zdGFydC1wcmV2ZW50LnByZWRpY2F0ZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZnVuY3MvYXV0by1zdGFydC1wcmV2ZW50LnByZWRpY2F0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7O0FBMkdIOzs7R0FHRztBQUNVLFFBQUEscUJBQXFCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDM0MsVUFBVTtJQUNWLGlDQUFpQztJQUNqQyxZQUFZO0lBQ1osV0FBVztJQUNYLFVBQVU7Q0FDWCxDQUFDLENBQUM7QUFFSDs7Ozs7R0FLRztBQUNJLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxNQUFjLEVBQVcsRUFBRSxDQUM5RCw2QkFBcUIsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7QUFEdkIsUUFBQSxvQkFBb0Isd0JBQ0c7QUFFcEM7Ozs7Ozs7O0dBUUc7QUFDSSxNQUFNLGFBQWEsR0FBRyxDQUFDLEtBQWMsRUFBd0IsRUFBRTtJQUNwRSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFLENBQUM7UUFDL0MsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQ0QsSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNqRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxPQUFPLE9BQU8sS0FBSyxDQUFDLEtBQUssS0FBSyxRQUFRO1FBQ3BDLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDdEIsT0FBTyxLQUFLLENBQUMsT0FBTyxLQUFLLFFBQVE7UUFDakMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBQzdCLENBQUMsQ0FBQztBQVhXLFFBQUEsYUFBYSxpQkFXeEI7QUFFRjs7Ozs7R0FLRztBQUNJ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QUFDO0lBQ3BCLE1BQU0sRUFBRSxTQUFTO0lBQ2pCLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztJQUM3QixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87SUFDckIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO0lBQ25CLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtDQUM1QixDQUFDLENBQUM7QUFYVSxRQUFBLGtCQUFrQixzQkFXNUIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFB1cmUgaGVscGVycyBmb3IgdGhlIFJEUyBhdXRvLXN0YXJ0IHByZXZlbnQgTGFtYmRhLlxuICogTm8gQVdTIFNESywgRHVyYWJsZSBjb250ZXh0LCBlbnYsIG9yIGNsb2NrIGRlcGVuZGVuY2llcy5cbiAqL1xuXG4vKipcbiAqIERldGFpbCBwYXlsb2FkIG9mIGFuIFJEUyBhdXRvLXN0YXJ0IGV2ZW50IGZyb20gRXZlbnRCcmlkZ2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmRzQXV0b1N0YXJ0RGV0YWlsIHtcbiAgLyoqIEV2ZW50IElEOiBSRFMtRVZFTlQtMDE1NCAoREIgaW5zdGFuY2UpIG9yIFJEUy1FVkVOVC0wMTUzIChEQiBjbHVzdGVyKS4gKi9cbiAgRXZlbnRJRDogJ1JEUy1FVkVOVC0wMTU0JyB8ICdSRFMtRVZFTlQtMDE1Myc7XG4gIC8qKiBSZXNvdXJjZSB0eXBlIHRoYXQgZW1pdHRlZCB0aGUgZXZlbnQuICovXG4gIFNvdXJjZVR5cGU6ICdEQl9JTlNUQU5DRScgfCAnQ0xVU1RFUic7XG4gIC8qKiBBUk4gb2YgdGhlIERCIGluc3RhbmNlIG9yIGNsdXN0ZXIuICovXG4gIFNvdXJjZUFybjogc3RyaW5nO1xuICAvKiogREIgaW5zdGFuY2Ugb3IgY2x1c3RlciBpZGVudGlmaWVyIGZyb20gdGhlIGV2ZW50LiAqL1xuICBTb3VyY2VJZGVudGlmaWVyOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUkRTIGF1dG8tc3RhcnQgZXZlbnQgYXMgcmVjZWl2ZWQgZnJvbSBFdmVudEJyaWRnZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZHNBdXRvU3RhcnRFdmVudCB7XG4gICdkZXRhaWwtdHlwZSc6ICdSRFMgREIgSW5zdGFuY2UgRXZlbnQnIHwgJ1JEUyBEQiBDbHVzdGVyIEV2ZW50JztcbiAgJ3NvdXJjZSc6ICdhd3MucmRzJztcbiAgJ2RldGFpbCc6IFJkc0F1dG9TdGFydERldGFpbDtcbn1cblxuLyoqXG4gKiBUYWctYmFzZWQgZmlsdGVyIHBhcmFtZXRlcnMgZm9yIHRoZSBoYW5kbGVyLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dG9TdGFydFBhcmFtcyB7XG4gIC8qKiBUYWcga2V5IHRvIG1hdGNoIG9uIHRoZSByZXNvdXJjZS4gKi9cbiAgdGFnS2V5OiBzdHJpbmc7XG4gIC8qKiBBbGxvd2VkIHRhZyB2YWx1ZXM7IHRoZSByZXNvdXJjZSBpcyBwcm9jZXNzZWQgb25seSB3aGVuIGl0cyB0YWcgdmFsdWUgaXMgaW4gdGhpcyBsaXN0LiAqL1xuICB0YWdWYWx1ZXM6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFNsYWNrIGNyZWRlbnRpYWxzIHN0b3JlZCBpbiBTZWNyZXRzIE1hbmFnZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2xhY2tTZWNyZXQge1xuICAvKiogU2xhY2sgYm90IG9yIHVzZXIgT0F1dGggdG9rZW4uICovXG4gIHRva2VuOiBzdHJpbmc7XG4gIC8qKiBDaGFubmVsIElEIG9yIG5hbWUgdG8gcG9zdCBub3RpZmljYXRpb25zIHRvLiAqL1xuICBjaGFubmVsOiBzdHJpbmc7XG59XG5cbi8qKlxuICogTm9ybWFsaXplZCBoYW5kbGVyIGlucHV0OiBFdmVudEJyaWRnZSBldmVudCBhbmQgdGFnIGZpbHRlciBwYXJhbWV0ZXJzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dG9TdGFydFByZXZlbnRJbnB1dCB7XG4gIGV2ZW50OiBSZHNBdXRvU3RhcnRFdmVudDtcbiAgcGFyYW1zOiBBdXRvU3RhcnRQYXJhbXM7XG59XG5cbi8qKlxuICogSGFuZGxlciByZXN1bHQgd2hlbiBubyBzdG9wIGFjdGlvbiB3YXMgdGFrZW4uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm9PcFJlc3VsdCB7XG4gIGFjdGlvbjogJ25vLW9wJztcbiAgcmVhc29uOiAndGFnIG5vdCBtYXRjaGVkIG9yIG5vdCBmb3VuZCcgfCAnYWxyZWFkeSBzdG9wcGVkJztcbiAgc3RhdHVzOiBzdHJpbmc7XG59XG5cbi8qKlxuICogSGFuZGxlciByZXN1bHQgd2hlbiB0aGlzIGludm9jYXRpb24gY2FsbGVkIFN0b3BEQiogYW5kIHRoZSByZXNvdXJjZSByZWFjaGVkIGBzdG9wcGVkYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdG9wcGVkUmVzdWx0IHtcbiAgYWN0aW9uOiAnc3RvcHBlZCc7XG4gIGZpbmFsU3RhdHVzOiBzdHJpbmc7XG4gIGFjY291bnQ6IHN0cmluZztcbiAgcmVnaW9uOiBzdHJpbmc7XG4gIGlkZW50aWZpZXI6IHN0cmluZztcbn1cblxuLyoqXG4gKiBBV1Mtc3R5bGUgdGFnIChLZXkvVmFsdWUpLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRhZyB7XG4gIEtleT86IHN0cmluZztcbiAgVmFsdWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogU3RhdGUgc25hcHNob3Qgd2hpbGUgd2FpdGluZyBvbiBSRFMgZGVzY3JpYmUgQVBJcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXYWl0U3RhdGUge1xuICAvKiogQ3VycmVudCBEQiBpbnN0YW5jZSBvciBjbHVzdGVyIHN0YXR1cy4gKi9cbiAgc3RhdHVzOiBzdHJpbmc7XG4gIC8qKiBEQiBpbnN0YW5jZSBvciBjbHVzdGVyIGlkZW50aWZpZXIuICovXG4gIGlkZW50aWZpZXI6IHN0cmluZztcbiAgLyoqIFRhZ3MgZnJvbSB0aGUgZGVzY3JpYmUgcmVzcG9uc2U7IHByZXNlbnQgb24gdGhlIGZpcnN0IHdhaXQgY2hlY2sgb25seS4gKi9cbiAgdGFncz86IFRhZ1tdO1xufVxuXG4vKiogQ29udGludWUgd2FpdGluZyB3aXRoIGEgZGVsYXkuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRpbnVlV2FpdCB7XG4gIHNob3VsZENvbnRpbnVlOiB0cnVlO1xuICBkZWxheTogeyBtaW51dGVzOiBudW1iZXIgfTtcbn1cblxuLyoqIFN0b3Agd2FpdGluZy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RvcFdhaXQge1xuICBzaG91bGRDb250aW51ZTogZmFsc2U7XG59XG5cbi8qKiBSZXN1bHQgb2YgYSBkdXJhYmxlIHdhaXRTdHJhdGVneS4gKi9cbmV4cG9ydCB0eXBlIFdhaXRTdHJhdGVneVJlc3VsdCA9IENvbnRpbnVlV2FpdCB8IFN0b3BXYWl0O1xuXG4vKipcbiAqIFJEUyBzdGF0dXNlcyB0aGF0IGluZGljYXRlIGFuIGluLXByb2dyZXNzIHRyYW5zaXRpb24uXG4gKiBUaGUgaGFuZGxlciB3YWl0cyBldmVyeSA1IG1pbnV0ZXMgd2hpbGUgdGhlIHJlc291cmNlIHJlbWFpbnMgaW4gb25lIG9mIHRoZXNlIHN0YXRlcy5cbiAqL1xuZXhwb3J0IGNvbnN0IFRSQU5TSVRJT05BTF9TVEFUVVNFUyA9IG5ldyBTZXQoW1xuICAnc3RhcnRpbmcnLFxuICAnY29uZmlndXJpbmctZW5oYW5jZWQtbW9uaXRvcmluZycsXG4gICdiYWNraW5nLXVwJyxcbiAgJ21vZGlmeWluZycsXG4gICdzdG9wcGluZycsXG5dKTtcblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgd2hlbiB0aGUgc3RhdHVzIGlzIHRyYW5zaXRpb25hbCBhbmQgd2FpdGluZyBzaG91bGQgY29udGludWUuXG4gKlxuICogQHBhcmFtIHN0YXR1cyAtIEN1cnJlbnQgREIgaW5zdGFuY2Ugb3IgY2x1c3RlciBzdGF0dXMuXG4gKiBAcmV0dXJucyBXaGV0aGVyIHRoZSBzdGF0dXMgaXMgdHJhbnNpdGlvbmFsLlxuICovXG5leHBvcnQgY29uc3QgaXNUcmFuc2l0aW9uYWxTdGF0dXMgPSAoc3RhdHVzOiBzdHJpbmcpOiBib29sZWFuID0+XG4gIFRSQU5TSVRJT05BTF9TVEFUVVNFUy5oYXMoc3RhdHVzKTtcblxuLyoqXG4gKiBUeXBlIGd1YXJkIGZvciBTbGFjayBjcmVkZW50aWFscyByZXR1cm5lZCBieSBgc2VjcmV0RmV0Y2hlci5nZXRTZWNyZXRWYWx1ZWAuXG4gKlxuICogYXdzLWxhbWJkYS1zZWNyZXQtZmV0Y2hlciBeMC43IHBhcnNlcyBTZWNyZXRTdHJpbmcgd2l0aCBxdWlldC1qc29uLXBhcnNlciBhbmRcbiAqIGZhbGxzIGJhY2sgdG8gdGhlIHJhdyBzdHJpbmcgb24gaW52YWxpZCBKU09OLCBzbyBjYWxsZXJzIG11c3QgdmFsaWRhdGUgc2hhcGUuXG4gKlxuICogQHBhcmFtIHZhbHVlIC0gVmFsdWUgcmV0dXJuZWQgZnJvbSB0aGUgc2VjcmV0IGZldGNoZXIuXG4gKiBAcmV0dXJucyBXaGV0aGVyIHZhbHVlIGlzIGEgU2xhY2tTZWNyZXQgd2l0aCBub24tZW1wdHkgdG9rZW4gYW5kIGNoYW5uZWwuXG4gKi9cbmV4cG9ydCBjb25zdCBpc1NsYWNrU2VjcmV0ID0gKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgU2xhY2tTZWNyZXQgPT4ge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JyB8fCB2YWx1ZSA9PSBudWxsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmICghKCd0b2tlbicgaW4gdmFsdWUpIHx8ICEoJ2NoYW5uZWwnIGluIHZhbHVlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHlwZW9mIHZhbHVlLnRva2VuID09PSAnc3RyaW5nJyAmJlxuICAgIHZhbHVlLnRva2VuLmxlbmd0aCA+IDAgJiZcbiAgICB0eXBlb2YgdmFsdWUuY2hhbm5lbCA9PT0gJ3N0cmluZycgJiZcbiAgICB2YWx1ZS5jaGFubmVsLmxlbmd0aCA+IDA7XG59O1xuXG4vKipcbiAqIFR5cGUgZ3VhcmQ6IGlucHV0IGlzIGB7IGV2ZW50LCBwYXJhbXMgfWAgYXMgcHJvZHVjZWQgYnkgdGhlIEV2ZW50QnJpZGdlIHRhcmdldC5cbiAqXG4gKiBAcGFyYW0gaW5wdXQgLSBSYXcgTGFtYmRhIGludm9jYXRpb24gcGF5bG9hZC5cbiAqIEByZXR1cm5zIFdoZXRoZXIgaW5wdXQgaGFzIG5vbi1udWxsIGV2ZW50IGFuZCBwYXJhbXMuXG4gKi9cbmV4cG9ydCBjb25zdCBpc0F1dG9TdGFydFByZXZlbnRJbnB1dCA9IChpbnB1dDogdW5rbm93bik6IGlucHV0IGlzIEF1dG9TdGFydFByZXZlbnRJbnB1dCA9PiB7XG4gIGlmICh0eXBlb2YgaW5wdXQgIT09ICdvYmplY3QnIHx8IGlucHV0ID09IG51bGwpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKCEoJ2V2ZW50JyBpbiBpbnB1dCkgfHwgISgncGFyYW1zJyBpbiBpbnB1dCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIGlucHV0LmV2ZW50ICE9IG51bGwgJiYgaW5wdXQucGFyYW1zICE9IG51bGw7XG59O1xuXG4vKipcbiAqIE5vcm1hbGl6ZXMgaW52b2NhdGlvbiBpbnB1dCB0byB7QGxpbmsgQXV0b1N0YXJ0UHJldmVudElucHV0fS5cbiAqXG4gKiBAcGFyYW0gaW5wdXQgLSBgeyBldmVudCwgcGFyYW1zIH1gIGZyb20gRXZlbnRCcmlkZ2UgSW5wdXRUcmFuc2Zvcm1lciAob3IgdGhlIHNhbWUgc2hhcGUgb24gZGlyZWN0IEludm9rZSkuXG4gKiBAcmV0dXJucyBFdmVudCBwbHVzIHRhZyBmaWx0ZXIgcGFyYW1ldGVycy5cbiAqIEB0aHJvd3MgV2hlbiB0aGUgcGF5bG9hZCBpcyBub3QgYHsgZXZlbnQsIHBhcmFtcyB9YC5cbiAqL1xuZXhwb3J0IGNvbnN0IG5vcm1hbGl6ZUlucHV0ID0gKGlucHV0OiB1bmtub3duKTogQXV0b1N0YXJ0UHJldmVudElucHV0ID0+IHtcbiAgaWYgKGlzQXV0b1N0YXJ0UHJldmVudElucHV0KGlucHV0KSkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQ6IGV4cGVjdGVkIHsgZXZlbnQsIHBhcmFtcyB9LicpO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHJlc291cmNlIGhhcyBhIHRhZyB3aXRoIHRoZSBnaXZlbiBrZXkgYW5kIGEgdmFsdWUgaW4gdGhlIGFsbG93ZWQgbGlzdC5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGFnIGtleSBhbmQgYWxsb3dlZCB2YWx1ZXMuXG4gKiBAcGFyYW0gdGFncyAtIFJlc291cmNlIHRhZyBsaXN0IChlLmcuIGZyb20gRGVzY3JpYmVEQkluc3RhbmNlcyAvIERlc2NyaWJlREJDbHVzdGVycykuXG4gKiBAcmV0dXJucyBXaGV0aGVyIHRoZSB0YWcgbWF0Y2hlcy5cbiAqL1xuZXhwb3J0IGNvbnN0IG1hdGNoVGFnID0gKHBhcmFtczogQXV0b1N0YXJ0UGFyYW1zLCB0YWdzPzogVGFnW10pOiBib29sZWFuID0+IHtcbiAgaWYgKCF0YWdzIHx8IHRhZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IHZhbHVlID0gdGFncy5maW5kKHQgPT4gdC5LZXkgPT09IHBhcmFtcy50YWdLZXkpPy5WYWx1ZTtcbiAgaWYgKCF2YWx1ZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gcGFyYW1zLnRhZ1ZhbHVlcy5pbmNsdWRlcyh2YWx1ZSk7XG59O1xuXG4vKipcbiAqIFdoZXRoZXIgdGhlIEV2ZW50QnJpZGdlIGRldGFpbCBpZGVudGlmaWVzIGEgc3VwcG9ydGVkIERCIGluc3RhbmNlIGF1dG8tc3RhcnQgZXZlbnQuXG4gKlxuICogQHBhcmFtIGRldGFpbFR5cGUgLSBFdmVudEJyaWRnZSBkZXRhaWwtdHlwZS5cbiAqIEBwYXJhbSBkZXRhaWwgLSBSRFMgZXZlbnQgZGV0YWlsLlxuICogQHJldHVybnMgVHJ1ZSBmb3IgUkRTLUVWRU5ULTAxNTQgb24gYSBEQiBpbnN0YW5jZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGlzRGJJbnN0YW5jZUF1dG9TdGFydCA9IChcbiAgZGV0YWlsVHlwZTogUmRzQXV0b1N0YXJ0RXZlbnRbJ2RldGFpbC10eXBlJ10sXG4gIGRldGFpbDogUmRzQXV0b1N0YXJ0RGV0YWlsLFxuKTogYm9vbGVhbiA9PlxuICBkZXRhaWxUeXBlID09PSAnUkRTIERCIEluc3RhbmNlIEV2ZW50JyAmJlxuICBkZXRhaWwuU291cmNlVHlwZSA9PT0gJ0RCX0lOU1RBTkNFJyAmJlxuICBkZXRhaWwuRXZlbnRJRCA9PT0gJ1JEUy1FVkVOVC0wMTU0JztcblxuLyoqXG4gKiBXaGV0aGVyIHRoZSBFdmVudEJyaWRnZSBkZXRhaWwgaWRlbnRpZmllcyBhIHN1cHBvcnRlZCBEQiBjbHVzdGVyIGF1dG8tc3RhcnQgZXZlbnQuXG4gKlxuICogQHBhcmFtIGRldGFpbFR5cGUgLSBFdmVudEJyaWRnZSBkZXRhaWwtdHlwZS5cbiAqIEBwYXJhbSBkZXRhaWwgLSBSRFMgZXZlbnQgZGV0YWlsLlxuICogQHJldHVybnMgVHJ1ZSBmb3IgUkRTLUVWRU5ULTAxNTMgb24gYSBjbHVzdGVyLlxuICovXG5leHBvcnQgY29uc3QgaXNEYkNsdXN0ZXJBdXRvU3RhcnQgPSAoXG4gIGRldGFpbFR5cGU6IFJkc0F1dG9TdGFydEV2ZW50WydkZXRhaWwtdHlwZSddLFxuICBkZXRhaWw6IFJkc0F1dG9TdGFydERldGFpbCxcbik6IGJvb2xlYW4gPT5cbiAgZGV0YWlsVHlwZSA9PT0gJ1JEUyBEQiBDbHVzdGVyIEV2ZW50JyAmJlxuICBkZXRhaWwuU291cmNlVHlwZSA9PT0gJ0NMVVNURVInICYmXG4gIGRldGFpbC5FdmVudElEID09PSAnUkRTLUVWRU5ULTAxNTMnO1xuXG4vKipcbiAqIFdhaXQgc3RyYXRlZ3kgd2hpbGUgZGVzY3JpYmluZyB1bnRpbCB0aGUgcmVzb3VyY2UgbGVhdmVzIHRyYW5zaXRpb25hbCBzdGF0dXNlcy5cbiAqXG4gKiBAcGFyYW0gc3RhdGUgLSBMYXRlc3Qgd2FpdCBzdGF0ZS5cbiAqIEByZXR1cm5zIENvbnRpbnVlIGV2ZXJ5IDUgbWludXRlcyB3aGlsZSB0cmFuc2l0aW9uYWw7IG90aGVyd2lzZSBzdG9wLlxuICovXG5leHBvcnQgY29uc3Qgd2FpdFN0cmF0ZWd5VW50aWxTdGFibGUgPSAoc3RhdGU6IFdhaXRTdGF0ZSk6IFdhaXRTdHJhdGVneVJlc3VsdCA9PiB7XG4gIGlmIChpc1RyYW5zaXRpb25hbFN0YXR1cyhzdGF0ZS5zdGF0dXMpKSB7XG4gICAgcmV0dXJuIHsgc2hvdWxkQ29udGludWU6IHRydWUsIGRlbGF5OiB7IG1pbnV0ZXM6IDUgfSB9O1xuICB9XG4gIHJldHVybiB7IHNob3VsZENvbnRpbnVlOiBmYWxzZSB9O1xufTtcblxuLyoqXG4gKiBXYWl0IHN0cmF0ZWd5IGFmdGVyIFN0b3BEQiogdW50aWwgdGhlIHJlc291cmNlIHJlYWNoZXMgYHN0b3BwZWRgLlxuICpcbiAqIEBwYXJhbSBzdGF0ZSAtIExhdGVzdCB3YWl0IHN0YXRlLlxuICogQHJldHVybnMgU3RvcCB3aGVuIGBzdG9wcGVkYDsgY29udGludWUgd2hpbGUgdHJhbnNpdGlvbmFsLlxuICogQHRocm93cyBXaGVuIHRoZSBzdGF0dXMgaXMgbmVpdGhlciBzdG9wcGVkIG5vciB0cmFuc2l0aW9uYWwuXG4gKi9cbmV4cG9ydCBjb25zdCB3YWl0U3RyYXRlZ3lVbnRpbFN0b3BwZWQgPSAoc3RhdGU6IFdhaXRTdGF0ZSk6IFdhaXRTdHJhdGVneVJlc3VsdCA9PiB7XG4gIGlmIChzdGF0ZS5zdGF0dXMgPT09ICdzdG9wcGVkJykge1xuICAgIHJldHVybiB7IHNob3VsZENvbnRpbnVlOiBmYWxzZSB9O1xuICB9XG4gIGlmIChpc1RyYW5zaXRpb25hbFN0YXR1cyhzdGF0ZS5zdGF0dXMpKSB7XG4gICAgcmV0dXJuIHsgc2hvdWxkQ29udGludWU6IHRydWUsIGRlbGF5OiB7IG1pbnV0ZXM6IDUgfSB9O1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCBzdGF0dXMgd2hpbGUgd2FpdGluZyBmb3Igc3RvcDogJHtzdGF0ZS5zdGF0dXN9YCk7XG59O1xuXG4vKipcbiAqIERlY2lzaW9uIGFmdGVyIHRoZSBmaXJzdCBkZXNjcmliZSBhbmQgYSBzdWNjZXNzZnVsIHRhZyBtYXRjaC5cbiAqL1xuZXhwb3J0IHR5cGUgQWZ0ZXJUYWdNYXRjaERlY2lzaW9uID1cbiAgfCB7IGtpbmQ6ICdzdG9wJyB9XG4gIHwgeyBraW5kOiAnbm8tb3AnOyByZXN1bHQ6IE5vT3BSZXN1bHQgfVxuICB8IHsga2luZDogJ2Vycm9yJzsgbWVzc2FnZTogc3RyaW5nIH07XG5cbi8qKlxuICogRGVjaWRlcyB0aGUgbmV4dCBhY3Rpb24gd2hlbiB0YWdzIG1hdGNoZWQgYW5kIFN0b3BEQiogaGFzIG5vdCBiZWVuIGNhbGxlZCB5ZXQuXG4gKlxuICogQHBhcmFtIHN0YXR1cyAtIFN0YXR1cyBmcm9tIHRoZSBmaXJzdCBkZXNjcmliZSBhZnRlciBsZWF2aW5nIHRyYW5zaXRpb25hbCBzdGF0ZXMuXG4gKiBAcmV0dXJucyBTdG9wIHdoZW4gYGF2YWlsYWJsZWA7IG5vLW9wIHdoZW4gYWxyZWFkeSBgc3RvcHBlZGA7IG90aGVyd2lzZSBlcnJvci5cbiAqL1xuZXhwb3J0IGNvbnN0IGRlY2lkZUFmdGVyVGFnTWF0Y2ggPSAoc3RhdHVzOiBzdHJpbmcpOiBBZnRlclRhZ01hdGNoRGVjaXNpb24gPT4ge1xuICBpZiAoc3RhdHVzID09PSAnYXZhaWxhYmxlJykge1xuICAgIHJldHVybiB7IGtpbmQ6ICdzdG9wJyB9O1xuICB9XG4gIGlmIChzdGF0dXMgPT09ICdzdG9wcGVkJykge1xuICAgIHJldHVybiB7XG4gICAgICBraW5kOiAnbm8tb3AnLFxuICAgICAgcmVzdWx0OiB7XG4gICAgICAgIGFjdGlvbjogJ25vLW9wJyxcbiAgICAgICAgcmVhc29uOiAnYWxyZWFkeSBzdG9wcGVkJyxcbiAgICAgICAgc3RhdHVzLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG4gIHJldHVybiB7XG4gICAga2luZDogJ2Vycm9yJyxcbiAgICBtZXNzYWdlOiBgREIgc3RhdHVzIGlzIG5vdCBzdG9wcGVkIGFmdGVyIHByb2Nlc3Npbmc6ICR7c3RhdHVzfWAsXG4gIH07XG59O1xuXG4vKipcbiAqIEJ1aWxkcyB0aGUgbm8tb3AgcmVzdWx0IHVzZWQgd2hlbiB0YWdzIGRvIG5vdCBtYXRjaC5cbiAqXG4gKiBAcGFyYW0gc3RhdHVzIC0gQ3VycmVudCByZXNvdXJjZSBzdGF0dXMuXG4gKiBAcmV0dXJucyBOby1vcCByZXN1bHQgd2l0aCB0YWcgbWlzbWF0Y2ggcmVhc29uLlxuICovXG5leHBvcnQgY29uc3QgdGFnTWlzbWF0Y2hOb09wID0gKHN0YXR1czogc3RyaW5nKTogTm9PcFJlc3VsdCA9PiAoe1xuICBhY3Rpb246ICduby1vcCcsXG4gIHJlYXNvbjogJ3RhZyBub3QgbWF0Y2hlZCBvciBub3QgZm91bmQnLFxuICBzdGF0dXMsXG59KTtcblxuLyoqXG4gKiBQYXJzZXMgcmVnaW9uIGFuZCBhY2NvdW50IGZyb20gYW4gUkRTIHJlc291cmNlIEFSTiAoYGFybjphd3M6cmRzOnJlZ2lvbjphY2NvdW50Oi4uLmApLlxuICpcbiAqIEBwYXJhbSBzb3VyY2VBcm4gLSBTb3VyY2VBcm4gZnJvbSB0aGUgUkRTIGV2ZW50IGRldGFpbC5cbiAqIEByZXR1cm5zIFJlZ2lvbiBhbmQgYWNjb3VudCBpZCBzZWdtZW50cy5cbiAqL1xuZXhwb3J0IGNvbnN0IHBhcnNlUmRzU291cmNlQXJuID0gKHNvdXJjZUFybjogc3RyaW5nKTogeyByZWdpb246IHN0cmluZzsgYWNjb3VudDogc3RyaW5nIH0gPT4ge1xuICBjb25zdCBwYXJ0cyA9IHNvdXJjZUFybi5zcGxpdCgnOicpO1xuICByZXR1cm4ge1xuICAgIHJlZ2lvbjogcGFydHNbM10gPz8gJycsXG4gICAgYWNjb3VudDogcGFydHNbNF0gPz8gJycsXG4gIH07XG59O1xuXG4vKipcbiAqIEFyZ3VtZW50cyBmb3IgdGhlIFNsYWNrIHN0b3Atc3VjY2VzcyBub3RpZmljYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2xhY2tTdG9wTm90aWZpY2F0aW9uQXJncyB7XG4gIGNoYW5uZWw6IHN0cmluZztcbiAgc291cmNlVHlwZTogUmRzQXV0b1N0YXJ0RGV0YWlsWydTb3VyY2VUeXBlJ107XG4gIHNvdXJjZUlkZW50aWZpZXI6IHN0cmluZztcbiAgYWNjb3VudDogc3RyaW5nO1xuICByZWdpb246IHN0cmluZztcbn1cblxuLyoqXG4gKiBCdWlsZHMgdGhlIFNsYWNrIGBjaGF0LnBvc3RNZXNzYWdlYCBwYXlsb2FkIGFmdGVyIGEgc3VjY2Vzc2Z1bCBzdG9wLlxuICpcbiAqIEBwYXJhbSBhcmdzIC0gQ2hhbm5lbCBhbmQgcmVzb3VyY2UgaWRlbnRpdHkgZmllbGRzLlxuICogQHJldHVybnMgQXJndW1lbnRzIHN1aXRhYmxlIGZvciBgV2ViQ2xpZW50LmNoYXQucG9zdE1lc3NhZ2VgLlxuICovXG5leHBvcnQgY29uc3QgYnVpbGRTbGFja1N0b3BOb3RpZmljYXRpb24gPSAoYXJnczogU2xhY2tTdG9wTm90aWZpY2F0aW9uQXJncykgPT4gKHtcbiAgY2hhbm5lbDogYXJncy5jaGFubmVsLFxuICBhdHRhY2htZW50czogW1xuICAgIHtcbiAgICAgIGNvbG9yOiAnIzM2YTY0ZicsXG4gICAgICBwcmV0ZXh0OiBg8J+YtCBTdWNjZXNzZnVsbHkgc3RvcHBlZCB0aGUgYXV0b21hdGljYWxseSBydW5uaW5nIFJEUyAke2FyZ3Muc291cmNlVHlwZX0gJHthcmdzLnNvdXJjZUlkZW50aWZpZXJ9LmAsXG4gICAgICBmaWVsZHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHRpdGxlOiAnQWNjb3VudCcsXG4gICAgICAgICAgdmFsdWU6IGFyZ3MuYWNjb3VudCxcbiAgICAgICAgICBzaG9ydDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHRpdGxlOiAnUmVnaW9uJyxcbiAgICAgICAgICB2YWx1ZTogYXJncy5yZWdpb24sXG4gICAgICAgICAgc2hvcnQ6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0aXRsZTogJ1R5cGUnLFxuICAgICAgICAgIHZhbHVlOiBhcmdzLnNvdXJjZVR5cGUsXG4gICAgICAgICAgc2hvcnQ6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0aXRsZTogJ0lkZW50aWZpZXInLFxuICAgICAgICAgIHZhbHVlOiBhcmdzLnNvdXJjZUlkZW50aWZpZXIsXG4gICAgICAgICAgc2hvcnQ6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0sXG4gIF0sXG59KTtcblxuLyoqXG4gKiBCdWlsZHMgdGhlIHN1Y2Nlc3MgcmVzdWx0IGFmdGVyIFN0b3BEQiogcmVhY2hlZCBgc3RvcHBlZGAuXG4gKlxuICogQHBhcmFtIGFyZ3MgLSBGaW5hbCBzdGF0dXMgYW5kIGlkZW50aXR5IGZpZWxkcy5cbiAqIEByZXR1cm5zIFN0b3BwZWRSZXN1bHQgZm9yIHRoZSBoYW5kbGVyIHJldHVybiB2YWx1ZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGJ1aWxkU3RvcHBlZFJlc3VsdCA9IChhcmdzOiB7XG4gIGZpbmFsU3RhdHVzOiBzdHJpbmc7XG4gIGFjY291bnQ6IHN0cmluZztcbiAgcmVnaW9uOiBzdHJpbmc7XG4gIGlkZW50aWZpZXI6IHN0cmluZztcbn0pOiBTdG9wcGVkUmVzdWx0ID0+ICh7XG4gIGFjdGlvbjogJ3N0b3BwZWQnLFxuICBmaW5hbFN0YXR1czogYXJncy5maW5hbFN0YXR1cyxcbiAgYWNjb3VudDogYXJncy5hY2NvdW50LFxuICByZWdpb246IGFyZ3MucmVnaW9uLFxuICBpZGVudGlmaWVyOiBhcmdzLmlkZW50aWZpZXIsXG59KTtcbiJdfQ==
|
|
@@ -8,7 +8,7 @@ const rds_database_auto_start_preventer_1 = require("../constructs/rds-database-
|
|
|
8
8
|
* CDK stack that deploys {@link RDSDatabaseAutoStartPreventer}.
|
|
9
9
|
*/
|
|
10
10
|
class RDSDatabaseAutoStartPreventStack extends aws_cdk_lib_1.Stack {
|
|
11
|
-
static [JSII_RTTI_SYMBOL_1] = { fqn: "rds-database-auto-start-preventer.RDSDatabaseAutoStartPreventStack", version: "0.
|
|
11
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "rds-database-auto-start-preventer.RDSDatabaseAutoStartPreventStack", version: "0.3.0" };
|
|
12
12
|
/**
|
|
13
13
|
* Creates the stack and the RDSDatabaseAutoStartPreventer construct.
|
|
14
14
|
*
|
package/package.json
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@typescript-eslint/eslint-plugin": "^8",
|
|
52
52
|
"@typescript-eslint/parser": "^8",
|
|
53
53
|
"aws-cdk-lib": "2.232.0",
|
|
54
|
-
"aws-lambda-secret-fetcher": "^0.
|
|
54
|
+
"aws-lambda-secret-fetcher": "^0.7.1",
|
|
55
55
|
"aws-sdk-client-mock": "^4.1.0",
|
|
56
56
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
57
57
|
"commit-and-tag-version": "^12",
|
|
@@ -62,15 +62,16 @@
|
|
|
62
62
|
"eslint-plugin-import": "^2.32.0",
|
|
63
63
|
"jest": "^30.4.2",
|
|
64
64
|
"jest-junit": "^17",
|
|
65
|
-
"jsii": "
|
|
65
|
+
"jsii": "6.0.x",
|
|
66
66
|
"jsii-diff": "^1.139.0",
|
|
67
67
|
"jsii-docgen": "^10.5.0",
|
|
68
68
|
"jsii-pacmak": "^1.139.0",
|
|
69
|
-
"jsii-rosetta": "
|
|
69
|
+
"jsii-rosetta": "6.0.x",
|
|
70
70
|
"projen": "^0.101.31",
|
|
71
|
+
"strict-env-resolver": "^0.6.1",
|
|
71
72
|
"ts-jest": "^29.4.12",
|
|
72
73
|
"ts-node": "^10.9.2",
|
|
73
|
-
"typescript": "
|
|
74
|
+
"typescript": "6.0.x"
|
|
74
75
|
},
|
|
75
76
|
"peerDependencies": {
|
|
76
77
|
"aws-cdk-lib": "^2.232.0",
|
|
@@ -87,8 +88,7 @@
|
|
|
87
88
|
},
|
|
88
89
|
"devEngines": {
|
|
89
90
|
"packageManager": {
|
|
90
|
-
"name": "
|
|
91
|
-
"version": "1.22.22",
|
|
91
|
+
"name": "npm",
|
|
92
92
|
"onFail": "ignore"
|
|
93
93
|
}
|
|
94
94
|
},
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"publishConfig": {
|
|
99
99
|
"access": "public"
|
|
100
100
|
},
|
|
101
|
-
"version": "0.
|
|
101
|
+
"version": "0.3.0",
|
|
102
102
|
"jest": {
|
|
103
103
|
"coverageProvider": "v8",
|
|
104
104
|
"testMatch": [
|